Skip to content

Commit 4ab9b93

Browse files
committed
refactor(Code generation): Code generation supports importing multiple .proto files
1 parent 7f9e07c commit 4ab9b93

File tree

13 files changed

+257
-61
lines changed

13 files changed

+257
-61
lines changed

common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/ActionMethodDocument.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public final class ActionMethodDocument {
4949
final boolean hasBizData;
5050
/** 方法参数的名字 */
5151
String bizDataName;
52-
/** 方法参数的 */
52+
/** 方法参数的类型 class */
53+
Class<?> bizDataTypeClazz;
54+
/** 方法参数的类型 */
5355
String bizDataType;
5456
/** 方法参数的注释 */
5557
String bizDataComment;
@@ -69,6 +71,8 @@ public final class ActionMethodDocument {
6971
/** 方法返回值的注释 */
7072
String returnComment;
7173
String returnDataName;
74+
/** 返回值类型 class */
75+
Class<?> returnTypeClazz;
7276
/** 返回值类型(原始的,即使参数是 List,也会取泛型) */
7377
String returnDataActualTypeName;
7478

@@ -105,7 +109,7 @@ public ActionMethodDocument(ActionCommandDoc actionCommandDoc, TypeMappingDocume
105109
extractedReturnInfo(actionCommand);
106110

107111
// --------- 方法参数相关 ---------
108-
ActionCommand.ParamInfo bizParam = getBizParam(actionCommand);
112+
ActionCommand.ParamInfo bizParam = DocumentAnalyseKit.getBizParam(actionCommand);
109113
this.hasBizData = Objects.nonNull(bizParam);
110114
if (this.hasBizData) {
111115
extractedParamInfo(bizParam, actionCommandDoc);
@@ -120,7 +124,7 @@ private void extractedReturnInfo(ActionCommand actionCommand) {
120124
this.isVoid = returnInfo.isVoid();
121125
this.returnDataIsList = returnInfo.isList();
122126

123-
Class<?> returnTypeClazz = returnInfo.getActualTypeArgumentClazz();
127+
this.returnTypeClazz = returnInfo.getActualTypeArgumentClazz();
124128
var typeMappingRecord = typeMappingDocument.getTypeMappingRecord(returnTypeClazz);
125129
this.returnDataName = typeMappingRecord.getParamTypeName();
126130
this.returnDataTypeIsInternal = typeMappingRecord.isInternalType();
@@ -131,9 +135,9 @@ private void extractedReturnInfo(ActionCommand actionCommand) {
131135
}
132136

133137
private void extractedParamInfo(ActionCommand.ParamInfo paramInfo, ActionCommandDoc actionCommandDoc) {
134-
Class<?> actualTypeArgumentClazz = paramInfo.getActualTypeArgumentClazz();
138+
this.bizDataTypeClazz = paramInfo.getActualTypeArgumentClazz();
135139
// 方法参数类型
136-
var typeMappingRecord = this.typeMappingDocument.getTypeMappingRecord(actualTypeArgumentClazz);
140+
var typeMappingRecord = this.typeMappingDocument.getTypeMappingRecord(bizDataTypeClazz);
137141
this.bizDataTypeIsList = paramInfo.isList();
138142
this.internalBizDataType = typeMappingRecord.isInternalType();
139143

@@ -146,11 +150,4 @@ private void extractedParamInfo(ActionCommand.ParamInfo paramInfo, ActionCommand
146150

147151
this.actualTypeName = typeMappingRecord.getParamTypeName();
148152
}
149-
150-
private ActionCommand.ParamInfo getBizParam(ActionCommand actionCommand) {
151-
return actionCommand.streamParamInfo()
152-
// 只处理业务参数
153-
.filter(ActionCommand.ParamInfo::isBizData)
154-
.findAny().orElse(null);
155-
}
156153
}

common/common-core/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentAnalyseKit.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package com.iohao.game.action.skeleton.core.doc;
2020

21+
import com.iohao.game.action.skeleton.core.ActionCommand;
2122
import com.iohao.game.action.skeleton.core.exception.ActionErrorEnum;
2223
import com.iohao.game.action.skeleton.core.exception.MsgExceptionInfo;
2324
import com.iohao.game.common.kit.CollKit;
@@ -153,4 +154,11 @@ private List<ErrorCodeDocument> analyseErrorCodeDocument(JavaClass javaClass) {
153154
return errorCodeDocument;
154155
}).filter(Objects::nonNull).toList();
155156
}
157+
158+
ActionCommand.ParamInfo getBizParam(ActionCommand actionCommand) {
159+
return actionCommand.streamParamInfo()
160+
// 只处理业务参数
161+
.filter(ActionCommand.ParamInfo::isBizData)
162+
.findAny().orElse(null);
163+
}
156164
}

common/common-micro-kit/src/main/java/com/iohao/game/common/kit/concurrent/TaskKit.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.netty.util.TimerTask;
3030
import lombok.Getter;
3131
import lombok.experimental.UtilityClass;
32+
import lombok.extern.slf4j.Slf4j;
3233

3334
import java.util.Objects;
3435
import java.util.Set;
@@ -141,6 +142,7 @@
141142
* @author 渔民小镇
142143
* @date 2023-12-02
143144
*/
145+
@Slf4j
144146
@UtilityClass
145147
public class TaskKit {
146148
/** 执行一些没有 io 操作的逻辑 */
@@ -283,12 +285,10 @@ public void runInterval(IntervalTaskListener taskListener, long tick, TimeUnit t
283285
}
284286

285287
private void foreverTimerTask(long tick, TimeUnit timeUnit, Set<IntervalTaskListener> set) {
286-
287288
// 启动定时器
288289
TaskKit.newTimeout(new TimerTask() {
289290
@Override
290291
public void run(Timeout timeout) {
291-
292292
if (set.isEmpty()) {
293293
TaskKit.newTimeout(this, tick, timeUnit);
294294
return;

widget/generate-code/src/main/java/com/iohao/game/action/skeleton/core/doc/CsharpDocumentGenerate.java

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@
2222
import com.iohao.game.action.skeleton.protocol.wrapper.IntValue;
2323
import com.iohao.game.action.skeleton.protocol.wrapper.LongValue;
2424
import com.iohao.game.action.skeleton.protocol.wrapper.StringValue;
25+
import com.iohao.game.common.kit.StrKit;
2526
import lombok.AccessLevel;
2627
import lombok.Getter;
2728
import lombok.Setter;
2829
import lombok.experimental.FieldDefaults;
2930
import lombok.extern.slf4j.Slf4j;
3031
import org.beetl.core.Template;
3132

32-
import java.util.HashMap;
33-
import java.util.List;
34-
import java.util.Map;
35-
import java.util.Objects;
33+
import java.util.*;
34+
import java.util.stream.Collectors;
3635

3736
/**
3837
* Generate C# code, such as broadcast, error code, action
@@ -47,17 +46,20 @@
4746
public final class CsharpDocumentGenerate extends AbstractDocumentGenerate {
4847
/** c# namespace that generate files */
4948
String namespace = "IoGame.Gen";
49+
@Setter(AccessLevel.PRIVATE)
50+
CsharpAnalyseImport analyseImport;
5051

5152
public CsharpDocumentGenerate() {
5253
this.typeMappingDocument = new CSharpTypeMappingDocument(this);
53-
protoImportPath = "using Pb.Common;";
54+
// protoImportPath = "using Pb.Common;";
5455
}
5556

5657
@Override
5758
public void generate(IoGameDocument ioGameDocument) {
5859
Objects.requireNonNull(this.path);
59-
60-
defaultValue();
60+
InternalProtoClassKit.analyseProtoClass(ioGameDocument);
61+
Map<Class<?>, ProtoFileMergeClass> protoClassMap = InternalProtoClassKit.protoClassMap;
62+
this.analyseImport = new CsharpAnalyseImport(protoClassMap.values());
6163

6264
this.generateAction(ioGameDocument);
6365
this.generateBroadcast(ioGameDocument);
@@ -66,15 +68,14 @@ public void generate(IoGameDocument ioGameDocument) {
6668
log.info("CSharpDocumentGenerate success: {}", this.path);
6769
}
6870

69-
private void defaultValue() {
70-
this.actionImportList.add(protoImportPath);
71-
this.broadcastImportList.add(protoImportPath);
72-
}
71+
// private void defaultValue() {
72+
// this.actionImportList.add(protoImportPath);
73+
// this.broadcastImportList.add(protoImportPath);
74+
// }
7375

7476
@Override
7577
protected void generateErrorCode(IoGameDocument ioGameDocument) {
7678
Template template = ofTemplate("game_code.txt");
77-
template.binding("using", String.join("\n", this.errorCodeImportList));
7879
template.binding("namespace", this.namespace);
7980

8081
new GameCodeGenerate()
@@ -93,7 +94,7 @@ protected void generateAction(IoGameDocument ioGameDocument) {
9394
actionDocumentList.forEach(actionDocument -> {
9495
Template template = ofTemplate("action.txt");
9596
// using、namespace
96-
template.binding("using", String.join("\n", this.actionImportList));
97+
// template.binding("using", String.join("\n", this.actionImportList));
9798
template.binding("namespace", this.namespace);
9899

99100
new ActionGenerate()
@@ -109,7 +110,7 @@ protected void generateAction(IoGameDocument ioGameDocument) {
109110
@Override
110111
protected void generateBroadcast(IoGameDocument ioGameDocument) {
111112
Template template = ofTemplate(DocumentGenerateKit.broadcastActionTemplatePath);
112-
template.binding("using", String.join("\n", this.broadcastImportList));
113+
// template.binding("using", String.join("\n", this.broadcastImportList));
113114
template.binding("namespace", this.namespace);
114115

115116
new BroadcastGenerate()
@@ -177,16 +178,49 @@ public TypeMappingRecord getTypeMappingRecord(Class<?> protoTypeClazz) {
177178
return map.get(protoTypeClazz);
178179
}
179180

180-
String simpleName = protoTypeClazz.getSimpleName();
181+
var analyseImport = this.documentGenerate.analyseImport;
182+
var protoMessage = analyseImport.getProtoMessage(protoTypeClazz);
183+
184+
String paramTypeName;
185+
if (Objects.nonNull(protoMessage)) {
186+
paramTypeName = protoMessage.getFullParamTypeName();
187+
} else {
188+
paramTypeName = protoTypeClazz.getSimpleName();
189+
}
181190

182191
var record = new TypeMappingRecord().setInternalType(false)
183-
.setParamTypeName(simpleName).setListParamTypeName("List<%s>".formatted(simpleName))
192+
.setParamTypeName(paramTypeName).setListParamTypeName("List<%s>".formatted(paramTypeName))
184193
.setOfMethodTypeName("").setOfMethodListTypeName("ValueList")
185-
.setResultMethodTypeName("GetValue<%s>()".formatted(simpleName)).setResultMethodListTypeName("ListValue<%s>()".formatted(simpleName));
194+
.setResultMethodTypeName("GetValue<%s>()".formatted(paramTypeName)).setResultMethodListTypeName("ListValue<%s>()".formatted(paramTypeName));
186195

187196
map.put(protoTypeClazz, record);
188197

189198
return record;
190199
}
191200
}
201+
202+
private static class CsharpAnalyseImport {
203+
final Map<Class<?>, CsProtoMessage> map = new HashMap<>();
204+
205+
CsharpAnalyseImport(Collection<ProtoFileMergeClass> messageList) {
206+
messageList.forEach(protoFileMergeClass -> {
207+
String filePackage = Arrays.stream(protoFileMergeClass.filePackage().split("\\."))
208+
.map(StrKit::firstCharToUpperCase)
209+
.collect(Collectors.joining("."));
210+
211+
var message = new CsProtoMessage(filePackage, protoFileMergeClass.dataClass());
212+
map.put(message.dataClass, message);
213+
});
214+
}
215+
216+
CsProtoMessage getProtoMessage(Class<?> dataClass) {
217+
return map.get(dataClass);
218+
}
219+
}
220+
221+
private record CsProtoMessage(String filePackage, Class<?> dataClass) {
222+
String getFullParamTypeName() {
223+
return filePackage + "." + dataClass.getSimpleName();
224+
}
225+
}
192226
}

widget/generate-code/src/main/java/com/iohao/game/action/skeleton/core/doc/DocumentGenerateAbout.java

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@
1818
*/
1919
package com.iohao.game.action.skeleton.core.doc;
2020

21+
import com.iohao.game.action.skeleton.core.ActionCommand;
22+
import com.iohao.game.action.skeleton.protocol.wrapper.BoolValue;
23+
import com.iohao.game.action.skeleton.protocol.wrapper.IntValue;
24+
import com.iohao.game.action.skeleton.protocol.wrapper.LongValue;
25+
import com.iohao.game.action.skeleton.protocol.wrapper.StringValue;
2126
import com.iohao.game.common.kit.ArrayKit;
2227
import com.iohao.game.common.kit.StrKit;
2328
import com.iohao.game.common.kit.io.FileKit;
2429
import com.iohao.game.common.kit.time.FormatTimeKit;
30+
import com.iohao.game.widget.light.protobuf.ProtoFileMerge;
2531
import lombok.AccessLevel;
2632
import lombok.Getter;
2733
import lombok.Setter;
@@ -35,6 +41,7 @@
3541
import org.beetl.core.Template;
3642
import org.beetl.core.resource.ClasspathResourceLoader;
3743
import com.iohao.game.action.skeleton.core.exception.ActionErrorEnum;
44+
import org.jctools.maps.NonBlockingHashMap;
3845

3946
import java.io.File;
4047
import java.nio.charset.StandardCharsets;
@@ -85,7 +92,7 @@ public Object call(Object[] paras, Context ctx) {
8592
@FieldDefaults(level = AccessLevel.PRIVATE)
8693
final class GameCodeGenerate {
8794
IoGameDocument ioGameDocument;
88-
/** true : 生成框架内置的错误码, see {@link ActionErrorEnum} */
95+
/** true : 生成框架内置的错误码see {@link ActionErrorEnum} */
8996
boolean internalErrorCode;
9097

9198
Template template;
@@ -278,18 +285,88 @@ void binding(Template template) {
278285
}
279286
}
280287

288+
@UtilityClass
289+
class InternalProtoClassKit {
290+
final Map<Class<?>, ProtoFileMergeClass> protoClassMap = new NonBlockingHashMap<>();
291+
292+
void analyseProtoClass(IoGameDocument ioGameDocument) {
293+
if (!protoClassMap.isEmpty()) {
294+
return;
295+
}
296+
297+
// --------- collect proto class ---------
298+
final Set<Class<?>> protoClassSet = new HashSet<>();
299+
ioGameDocument.actionDocList.stream()
300+
.flatMap(actionDoc -> actionDoc.getActionCommandDocMap().values().stream())
301+
.forEach(actionCommandDoc -> {
302+
ActionCommand actionCommand = actionCommandDoc.getActionCommand();
303+
// --------- action return class ---------
304+
ActionCommand.ActionMethodReturnInfo returnInfo = actionCommand.getActionMethodReturnInfo();
305+
if (!returnInfo.isVoid()) {
306+
Class<?> returnTypeClazz = returnInfo.getActualTypeArgumentClazz();
307+
protoClassSet.add(returnTypeClazz);
308+
}
309+
310+
// --------- action param class ---------
311+
ActionCommand.ParamInfo bizParam = DocumentAnalyseKit.getBizParam(actionCommand);
312+
if (Objects.nonNull(bizParam)) {
313+
Class<?> actualTypeArgumentClazz = bizParam.getActualTypeArgumentClazz();
314+
protoClassSet.add(actualTypeArgumentClazz);
315+
}
316+
});
317+
318+
ioGameDocument.broadcastDocumentList.forEach(broadcastDocument -> {
319+
Class<?> dataClass = broadcastDocument.getDataClass();
320+
if (Objects.nonNull(dataClass)) {
321+
protoClassSet.add(dataClass);
322+
}
323+
});
324+
325+
var excludeTypeList = List.of(
326+
int.class, Integer.class, IntValue.class,
327+
long.class, Long.class, LongValue.class,
328+
boolean.class, Boolean.class, BoolValue.class,
329+
String.class, StringValue.class
330+
);
331+
332+
protoClassSet.stream().filter(protoClass -> {
333+
for (Class<?> aClass : excludeTypeList) {
334+
if (aClass == protoClass) {
335+
return false;
336+
}
337+
}
338+
339+
return protoClass.getAnnotation(ProtoFileMerge.class) != null;
340+
}).forEach(protoClass -> {
341+
ProtoFileMerge annotation = protoClass.getAnnotation(ProtoFileMerge.class);
342+
String fileName = annotation.fileName();
343+
String filePackage = annotation.filePackage();
344+
345+
var message = new ProtoFileMergeClass(fileName, filePackage, protoClass);
346+
protoClassMap.put(protoClass, message);
347+
});
348+
}
349+
}
350+
351+
record ProtoFileMergeClass(String fileName, String filePackage, Class<?> dataClass) {
352+
}
353+
281354
@Setter
282355
@FieldDefaults(level = AccessLevel.PACKAGE)
283356
abstract class AbstractDocumentGenerate implements DocumentGenerate {
284357
@Getter
358+
@Deprecated
285359
final Set<String> actionImportList = new LinkedHashSet<>();
286360
@Getter
361+
@Deprecated
287362
final Set<String> broadcastImportList = new LinkedHashSet<>();
288363
@Getter
364+
@Deprecated
289365
final Set<String> errorCodeImportList = new LinkedHashSet<>();
290366
/** true : generate ActionErrorEnum */
291367
boolean internalErrorCode = true;
292368
/** your .proto path */
369+
@Deprecated
293370
String protoImportPath;
294371
/**
295372
* The storage path of the generated files.

0 commit comments

Comments
 (0)