Commit eddd21f4e8287cd232b0fc07b2f1be8d6f83d840

Authored by haohao
1 parent 83ce168a

fix(infra): 修复 Windows 下 Codegen 单测

yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
@@ -457,8 +457,10 @@ public class CodegenEngine { @@ -457,8 +457,10 @@ public class CodegenEngine {
457 * @return 格式化后的代码 457 * @return 格式化后的代码
458 */ 458 */
459 private String prettyCode(String content, String vmPath) { 459 private String prettyCode(String content, String vmPath) {
460 - // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(内含换行归一化)  
461 - content = CodegenFormatUtils.applyVueTrailingCommaFix(content, vmPath); 460 + // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5、vue3_admin_uniapp)
  461 + if (!StrUtil.containsAny(vmPath, "vben5", "vue3_admin_uniapp")) {
  462 + content = content.replaceAll(",\\r?\\n}", "\n}").replaceAll(",\\r?\\n }", "\n }");
  463 + }
462 // Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到 464 // Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到
463 if (StrUtil.count(content, "dateFormatter") == 1) { 465 if (StrUtil.count(content, "dateFormatter") == 1) {
464 content = StrUtils.removeLineContains(content, "dateFormatter"); 466 content = StrUtils.removeLineContains(content, "dateFormatter");
@@ -480,7 +482,7 @@ public class CodegenEngine { @@ -480,7 +482,7 @@ public class CodegenEngine {
480 if (StrUtil.count(content, "DICT_TYPE.") == 0) { 482 if (StrUtil.count(content, "DICT_TYPE.") == 0) {
481 content = StrUtils.removeLineContains(content, "DICT_TYPE"); 483 content = StrUtils.removeLineContains(content, "DICT_TYPE");
482 } 484 }
483 - return CodegenFormatUtils.formatGeneratedContent(content); 485 + return content;
484 } 486 }
485 487
486 private Map<String, Object> initBindingMap(DbType dbType, CodegenTableDO table, List<CodegenColumnDO> columns, 488 private Map<String, Object> initBindingMap(DbType dbType, CodegenTableDO table, List<CodegenColumnDO> columns,
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenFormatUtils.java deleted
1 -package cn.iocoder.yudao.module.infra.service.codegen.inner;  
2 -  
3 -import cn.hutool.core.util.StrUtil;  
4 -  
5 -/**  
6 - * 代码生成结果格式化工具  
7 - */  
8 -final class CodegenFormatUtils {  
9 -  
10 - /**  
11 - * 经典 Vue2 模板目录,与 {@link CodegenEngine#vueTemplatePath(String)} 一致  
12 - */  
13 - private static final String CLASSIC_VUE2_TEMPLATE_PREFIX = "codegen/vue/";  
14 -  
15 - /**  
16 - * 经典 Vue3 模板目录,与 {@link CodegenEngine#vue3TemplatePath(String)} 一致。  
17 - * 使用前缀 {@code codegen/vue3/} 而非子串匹配,避免误伤 {@code vue3_vben5}、{@code vue3_admin_uniapp} 等目录。  
18 - */  
19 - private static final String CLASSIC_VUE3_TEMPLATE_PREFIX = "codegen/vue3/";  
20 -  
21 - private CodegenFormatUtils() {  
22 - }  
23 -  
24 - /**  
25 - * 经典 Vue2 / Vue3 模板(Element UI / Element Plus 标准模版)  
26 - */  
27 - static boolean isClassicVueTemplate(String vmPath) {  
28 - if (StrUtil.isEmpty(vmPath)) {  
29 - return false;  
30 - }  
31 - return StrUtil.startWith(vmPath, CLASSIC_VUE2_TEMPLATE_PREFIX)  
32 - || StrUtil.startWith(vmPath, CLASSIC_VUE3_TEMPLATE_PREFIX);  
33 - }  
34 -  
35 - /**  
36 - * 是否处理 {@code ,\n}} / {@code ,\n }} 形式的末尾逗号(经典 Vue + vue3_vben2;排除 vben5、uniapp)  
37 - */  
38 - static boolean needsVueTrailingCommaBeforeBraceFix(String vmPath) {  
39 - if (StrUtil.containsAny(vmPath, "vben5", "vue3_admin_uniapp")) {  
40 - return false;  
41 - }  
42 - return isClassicVueTemplate(vmPath) || StrUtil.startWith(vmPath, "codegen/vue3_vben/");  
43 - }  
44 -  
45 - /**  
46 - * 是否处理 {@code ,\n)} 形式的末尾逗号(仅经典 Vue 的 .vue 视图模板)  
47 - */  
48 - static boolean needsReactiveTrailingCommaFix(String vmPath) {  
49 - return isClassicVueTemplate(vmPath) && StrUtil.endWith(vmPath, ".vue.vm");  
50 - }  
51 -  
52 - /**  
53 - * Vue 模板:统一去除对象/参数列表末尾多余逗号(与 {@link CodegenEngine#prettyCode} 历史行为一致)  
54 - */  
55 - static String applyVueTrailingCommaFix(String content, String vmPath) {  
56 - if (content == null) {  
57 - return null;  
58 - }  
59 - content = normalizeLineSeparators(content);  
60 - if (needsVueTrailingCommaBeforeBraceFix(vmPath)) {  
61 - content = content.replaceAll(",\\r?\\n}", "\n}")  
62 - .replaceAll(",\\r?\\n }", "\n }");  
63 - }  
64 - if (needsReactiveTrailingCommaFix(vmPath)) {  
65 - content = removeTrailingCommaBeforeCloseParen(content);  
66 - }  
67 - return content;  
68 - }  
69 -  
70 - /**  
71 - * 去除多行实参中 {@code ,\n)} 形式的末尾逗号(如 {@code foo(bar,\n)};{@code reactive} 的 {@code ,\n})} 由 {@code ,\n}} 规则处理)  
72 - */  
73 - static String removeTrailingCommaBeforeCloseParen(String content) {  
74 - if (content == null) {  
75 - return null;  
76 - }  
77 - return content.replaceAll(",\\r?\\n\\)", "\n)");  
78 - }  
79 -  
80 - /**  
81 - * 统一换行符为 LF  
82 - */  
83 - static String normalizeLineSeparators(String content) {  
84 - if (content == null) {  
85 - return null;  
86 - }  
87 - return content.replace("\r\n", "\n").replace('\r', '\n');  
88 - }  
89 -  
90 - /**  
91 - * 生产生成结果:LF + 保证文件以单个换行结尾(符合 POSIX / IDE 习惯)  
92 - */  
93 - static String formatGeneratedContent(String content) {  
94 - content = normalizeLineSeparators(content);  
95 - if (StrUtil.isEmpty(content)) {  
96 - return content;  
97 - }  
98 - while (content.endsWith("\n\n")) {  
99 - content = content.substring(0, content.length() - 1);  
100 - }  
101 - if (!content.endsWith("\n")) {  
102 - content = content + "\n";  
103 - }  
104 - return content;  
105 - }  
106 -  
107 - /**  
108 - * 单测断言:LF + 去掉末尾空白(与历史 fixture 无尾换行对齐)  
109 - */  
110 - static String normalizeForAssert(String content) {  
111 - if (content == null) {  
112 - return null;  
113 - }  
114 - return normalizeLineSeparators(content).stripTrailing();  
115 - }  
116 -}  
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java
@@ -18,7 +18,12 @@ import org.mockito.Spy; @@ -18,7 +18,12 @@ import org.mockito.Spy;
18 18
19 import java.io.ByteArrayInputStream; 19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream; 20 import java.io.ByteArrayOutputStream;
21 -import java.util.*; 21 +import java.util.ArrayList;
  22 +import java.util.HashMap;
  23 +import java.util.LinkedHashSet;
  24 +import java.util.List;
  25 +import java.util.Map;
  26 +import java.util.Set;
22 27
23 import static org.junit.jupiter.api.Assertions.assertEquals; 28 import static org.junit.jupiter.api.Assertions.assertEquals;
24 29
@@ -99,17 +104,20 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest { @@ -99,17 +104,20 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest {
99 .map(m -> (String) m.get("filePath")) 104 .map(m -> (String) m.get("filePath"))
100 .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new)); 105 .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
101 assertEquals(expectedFiles, result.keySet(), "生成文件集合不匹配"); 106 assertEquals(expectedFiles, result.keySet(), "生成文件集合不匹配");
102 - // 校验每个文件;归一化换行符,让断言不依赖文件落盘的换行风格 107 + // 校验每个文件;归一化 \r\n 为 \n,让断言不依赖文件落盘的换行风格
103 asserts.forEach(assertMap -> { 108 asserts.forEach(assertMap -> {
104 String contentPath = (String) assertMap.get("contentPath"); 109 String contentPath = (String) assertMap.get("contentPath");
105 String filePath = (String) assertMap.get("filePath"); 110 String filePath = (String) assertMap.get("filePath");
106 - String expected = CodegenFormatUtils.normalizeForAssert(  
107 - ResourceUtil.readUtf8Str("codegen/" + path + "/" + contentPath));  
108 - String actual = CodegenFormatUtils.normalizeForAssert(result.get(filePath));  
109 - assertEquals(expected, actual, filePath + ":不匹配"); 111 + String expected = normalizeLineEndings(ResourceUtil.readUtf8Str("codegen/" + path + "/" + contentPath));
  112 + String actual = result.get(filePath);
  113 + assertEquals(expected, normalizeLineEndings(actual), filePath + ":不匹配");
110 }); 114 });
111 } 115 }
112 116
  117 + private static String normalizeLineEndings(String content) {
  118 + return content == null ? null : content.replace("\r\n", "\n").replace("\r", "\n").stripTrailing();
  119 + }
  120 +
113 // ==================== 调试专用 ==================== 121 // ==================== 调试专用 ====================
114 122
115 /** 123 /**
@@ -143,10 +151,10 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest { @@ -143,10 +151,10 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest {
143 + '/' + StrUtil.subBefore(lastFilePath, '.', true); 151 + '/' + StrUtil.subBefore(lastFilePath, '.', true);
144 asserts.add(MapUtil.<String, String>builder().put("filePath", filePath) 152 asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
145 .put("contentPath", contentPath).build()); 153 .put("contentPath", contentPath).build());
146 - FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath); 154 + FileUtil.writeUtf8String(normalizeLineEndings(fileContent), basePath + "/" + contentPath);
147 }); 155 });
148 // 写入 assert.json 文件 156 // 写入 assert.json 文件
149 - FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath + "/assert.json"); 157 + FileUtil.writeUtf8String(normalizeLineEndings(JsonUtils.toJsonPrettyString(asserts)), basePath + "/assert.json");
150 } 158 }
151 159
152 } 160 }
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenFormatUtilsTest.java deleted
1 -package cn.iocoder.yudao.module.infra.service.codegen.inner;  
2 -  
3 -import org.junit.jupiter.api.Test;  
4 -  
5 -import static org.junit.jupiter.api.Assertions.*;  
6 -  
7 -class CodegenFormatUtilsTest {  
8 -  
9 - @Test  
10 - void testNormalizeLineSeparators() {  
11 - assertEquals("a\nb", CodegenFormatUtils.normalizeLineSeparators("a\r\nb"));  
12 - assertEquals("a\nb", CodegenFormatUtils.normalizeLineSeparators("a\rb"));  
13 - }  
14 -  
15 - @Test  
16 - void testFormatGeneratedContent() {  
17 - assertEquals("class A {\n}\n", CodegenFormatUtils.formatGeneratedContent("class A {\r\n}\r\n"));  
18 - assertEquals("x\n", CodegenFormatUtils.formatGeneratedContent("x"));  
19 - assertEquals("x\n", CodegenFormatUtils.formatGeneratedContent("x\n\n\n"));  
20 - assertEquals("", CodegenFormatUtils.formatGeneratedContent(""));  
21 - assertEquals(" \n", CodegenFormatUtils.formatGeneratedContent(" "));  
22 - }  
23 -  
24 - @Test  
25 - void testNormalizeForAssert() {  
26 - assertEquals("}", CodegenFormatUtils.normalizeForAssert("}\n"));  
27 - assertEquals("a\nb", CodegenFormatUtils.normalizeForAssert("a\r\nb\r\n"));  
28 - }  
29 -  
30 - @Test  
31 - void testNormalizeForAssert_matchesFormatGeneratedContentForAssert() {  
32 - String raw = "package demo;\r\n\r\npublic class A {\r\n private Long id;\r\n}\r\n";  
33 - String generated = CodegenFormatUtils.formatGeneratedContent(raw);  
34 - assertEquals(CodegenFormatUtils.normalizeForAssert(raw),  
35 - CodegenFormatUtils.normalizeForAssert(generated));  
36 - }  
37 -  
38 - @Test  
39 - void testRemoveTrailingCommaBeforeCloseParen() {  
40 - assertEquals("foo(bar\n)", CodegenFormatUtils.removeTrailingCommaBeforeCloseParen("foo(bar,\n)"));  
41 - }  
42 -  
43 - @Test  
44 - void testApplyVueTrailingCommaFix_classicVueReactive() {  
45 - String input = "const queryParams = reactive({\n createTime: [],\n})\n";  
46 - String expected = "const queryParams = reactive({\n createTime: []\n})\n";  
47 - assertEquals(expected, CodegenFormatUtils.applyVueTrailingCommaFix(  
48 - input, "codegen/vue3/views/index.vue.vm"));  
49 - }  
50 -  
51 - @Test  
52 - void testApplyVueTrailingCommaFix_skipVben5() {  
53 - String input = "const x = {\n a: 1,\n}\n";  
54 - assertEquals(input, CodegenFormatUtils.applyVueTrailingCommaFix(  
55 - input, "codegen/vue3_vben5_antd/general/views/index.vue.vm"));  
56 - }  
57 -  
58 - @Test  
59 - void testIsClassicVueTemplate() {  
60 - assertTrue(CodegenFormatUtils.isClassicVueTemplate("codegen/vue/views/index.vue.vm"));  
61 - assertTrue(CodegenFormatUtils.isClassicVueTemplate("codegen/vue3/views/index.vue.vm"));  
62 - assertTrue(CodegenFormatUtils.isClassicVueTemplate("codegen/vue3/api/api.ts.vm"));  
63 - assertFalse(CodegenFormatUtils.isClassicVueTemplate("codegen/vue3_vben5_antd/schema/views/index.vue.vm"));  
64 - assertFalse(CodegenFormatUtils.isClassicVueTemplate("codegen/vue3_vben/views/index.vue.vm"));  
65 - assertFalse(CodegenFormatUtils.isClassicVueTemplate("codegen/vue3_admin_uniapp/views/index.vue.vm"));  
66 - assertFalse(CodegenFormatUtils.isClassicVueTemplate("codegen/vue30/views/index.vue.vm")); // 非 codegen/vue3/ 前缀  
67 - assertFalse(CodegenFormatUtils.isClassicVueTemplate("codegen/java/controller/controller.vm"));  
68 - assertFalse(CodegenFormatUtils.isClassicVueTemplate(null));  
69 - }  
70 -  
71 - @Test  
72 - void testNeedsReactiveTrailingCommaFix() {  
73 - assertTrue(CodegenFormatUtils.needsReactiveTrailingCommaFix("codegen/vue3/views/index.vue.vm"));  
74 - assertFalse(CodegenFormatUtils.needsReactiveTrailingCommaFix("codegen/vue3/api/api.ts.vm"));  
75 - assertFalse(CodegenFormatUtils.needsReactiveTrailingCommaFix("codegen/vue3_vben5_antd/general/views/index.vue.vm"));  
76 - }  
77 -  
78 - @Test  
79 - void testNeedsVueTrailingCommaBeforeBraceFix() {  
80 - assertTrue(CodegenFormatUtils.needsVueTrailingCommaBeforeBraceFix("codegen/vue3/views/index.vue.vm"));  
81 - assertTrue(CodegenFormatUtils.needsVueTrailingCommaBeforeBraceFix("codegen/vue3_vben/views/index.vue.vm"));  
82 - assertFalse(CodegenFormatUtils.needsVueTrailingCommaBeforeBraceFix("codegen/vue3_vben5_antd/general/views/index.vue.vm"));  
83 - assertFalse(CodegenFormatUtils.needsVueTrailingCommaBeforeBraceFix("codegen/vue3_admin_uniapp/views/index.vue.vm"));  
84 - }  
85 -}  
86 -