@ai-dev-tools/csharp-copilot-core 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/ReadMe.md +0 -2
  2. package/out/batch/generateCodeTests.js +22 -6
  3. package/out/batch/generateCodeTests.js.map +1 -1
  4. package/out/changedFilesProcessor/processChangedFiles.d.ts +9 -0
  5. package/out/changedFilesProcessor/processChangedFiles.js +156 -0
  6. package/out/changedFilesProcessor/processChangedFiles.js.map +1 -0
  7. package/out/codebk/prompts/buildAfGuidelines_20251226.liquid +15 -0
  8. package/out/codebk/prompts/general/generalUtGuidelines_20251226.liquid +16 -0
  9. package/out/codebk/prompts/xap/xapUtGuideline_20251225.liquid +37 -0
  10. package/out/codebk/prompts/xap/xapUtGuideline_20251226.liquid +49 -0
  11. package/out/command/index.js +32 -0
  12. package/out/command/index.js.map +1 -1
  13. package/out/command/utGenWrapper.js +85 -4
  14. package/out/command/utGenWrapper.js.map +1 -1
  15. package/out/gen/autoFix.d.ts +2 -2
  16. package/out/gen/autoFix.js +88 -31
  17. package/out/gen/autoFix.js.map +1 -1
  18. package/out/gen/csharpUtGen.d.ts +1 -1
  19. package/out/gen/csharpUtGen.js +16 -13
  20. package/out/gen/csharpUtGen.js.map +1 -1
  21. package/out/gen/ensureValidLLMResponse.d.ts +5 -1
  22. package/out/gen/ensureValidLLMResponse.js +15 -3
  23. package/out/gen/ensureValidLLMResponse.js.map +1 -1
  24. package/out/gen/postGen/postGenMoreUTProcess.d.ts +25 -0
  25. package/out/gen/postGen/postGenMoreUTProcess.js +502 -0
  26. package/out/gen/postGen/postGenMoreUTProcess.js.map +1 -0
  27. package/out/gen/postGen/postGenProcess.d.ts +1 -1
  28. package/out/gen/postGen/postGenProcess.js +7 -7
  29. package/out/gen/postGen/postGenProcess.js.map +1 -1
  30. package/out/gen/postGen/repairRequiredNameSpaces.d.ts +17 -0
  31. package/out/gen/postGen/repairRequiredNameSpaces.js +87 -20
  32. package/out/gen/postGen/repairRequiredNameSpaces.js.map +1 -1
  33. package/out/llm/preparePrompt.d.ts +2 -1
  34. package/out/llm/preparePrompt.js +38 -4
  35. package/out/llm/preparePrompt.js.map +1 -1
  36. package/out/llm/prompt/buildAfGuidelines.liquid +8 -8
  37. package/out/llm/prompt/general/generalUtGuidelines.liquid +3 -0
  38. package/out/llm/prompt/moreUT/generateMoreUTSourceCode.liquid +4 -0
  39. package/out/llm/prompt/moreUT/generateMoreUtAutoFix.liquid +45 -0
  40. package/out/llm/prompt/moreUT/generateMoreUtTemplate.liquid +115 -0
  41. package/out/llm/prompt/moreUT/generateMoreUtTestCode.liquid +5 -0
  42. package/out/llm/prompt/moreUT/utGenerationGuidelines.liquid +15 -0
  43. package/out/llm/prompt/xap/xapUtGuideline.liquid +66 -15
  44. package/out/types/changedFilesResult.d.ts +37 -0
  45. package/out/types/changedFilesResult.js +3 -0
  46. package/out/types/changedFilesResult.js.map +1 -0
  47. package/out/types/constants.d.ts +1 -0
  48. package/out/types/constants.js +2 -1
  49. package/out/types/constants.js.map +1 -1
  50. package/out/types/genResult.d.ts +1 -1
  51. package/out/types/genResult.js.map +1 -1
  52. package/out/utils/checkXapCode.d.ts +1 -1
  53. package/out/utils/checkXapCode.js +14 -2
  54. package/out/utils/checkXapCode.js.map +1 -1
  55. package/out/utils/fileUtils.d.ts +1 -0
  56. package/out/utils/fileUtils.js +13 -0
  57. package/out/utils/fileUtils.js.map +1 -1
  58. package/out/utils/getCodeStructurePath.d.ts +4 -0
  59. package/out/utils/getCodeStructurePath.js +30 -0
  60. package/out/utils/getCodeStructurePath.js.map +1 -1
  61. package/out/utils/getTestFile.d.ts +18 -8
  62. package/out/utils/getTestFile.js +734 -59
  63. package/out/utils/getTestFile.js.map +1 -1
  64. package/out/utils/removeFailedTestMethods.d.ts +8 -0
  65. package/out/utils/removeFailedTestMethods.js +363 -0
  66. package/out/utils/removeFailedTestMethods.js.map +1 -1
  67. package/out/utils/verifyGeneratedCode.d.ts +2 -0
  68. package/out/utils/verifyGeneratedCode.js +17 -0
  69. package/out/utils/verifyGeneratedCode.js.map +1 -0
  70. package/package.json +4 -1
@@ -1,21 +1,101 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateUtCode = generateUtCode;
4
37
  exports.generateBatchUtCode = generateBatchUtCode;
5
38
  exports.generateUtBenchmark = generateUtBenchmark;
6
39
  const stdListener_1 = require("../vsPlugin/stdListener");
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
7
42
  const constants_1 = require("../types/constants");
8
43
  const generateCodeTests_1 = require("../batch/generateCodeTests");
9
44
  const csharpUtGen_1 = require("../gen/csharpUtGen");
10
45
  const generateBenchmarkReport_1 = require("../benchmark/generateBenchmarkReport");
46
+ /**
47
+ * Load changed test files from CLI args or config file
48
+ * Priority: config file (changedFilesConfig) > CLI args (changedTestFiles)
49
+ *
50
+ * @param argv - Command line arguments containing changedFilesConfig and/or changedTestFiles
51
+ * @returns Array of changed test file paths (normalized), or undefined if not provided
52
+ */
53
+ function loadChangedTestFiles(argv) {
54
+ let changedFiles = [];
55
+ // Load from config file (higher priority) - changedFilesConfig is string type
56
+ if (argv.changedFilesConfig) {
57
+ try {
58
+ const configPath = path.resolve(argv.changedFilesConfig);
59
+ if (!fs.existsSync(configPath)) {
60
+ console.warn(`Changed files config not found: ${configPath}`);
61
+ }
62
+ else {
63
+ const configContent = fs.readFileSync(configPath, 'utf-8');
64
+ const config = JSON.parse(configContent);
65
+ if (config.changedTestFiles && Array.isArray(config.changedTestFiles)) {
66
+ // Normalize paths
67
+ const normalizedFiles = config.changedTestFiles.map((f) => path.normalize(f));
68
+ changedFiles.push(...normalizedFiles);
69
+ console.log(`Loaded ${normalizedFiles.length} changed test files from config: ${configPath}`);
70
+ return Array.from(new Set(changedFiles));
71
+ }
72
+ }
73
+ }
74
+ catch (err) {
75
+ console.warn(`Failed to load changed files config: ${err.message}`);
76
+ }
77
+ }
78
+ // Load from CLI args (changedTestFiles is array type, each element is string)
79
+ if (argv.changedTestFiles && Array.isArray(argv.changedTestFiles)) {
80
+ // Normalize paths and remove duplicates
81
+ const cliFiles = argv.changedTestFiles;
82
+ const normalizedCliFiles = cliFiles.map((f) => path.normalize(f));
83
+ const uniqueCliFiles = normalizedCliFiles.filter((f) => !changedFiles.includes(f));
84
+ changedFiles.push(...uniqueCliFiles);
85
+ console.log(`Loaded ${uniqueCliFiles.length} changed test files from CLI args (--changedTestFiles)`);
86
+ return Array.from(new Set(changedFiles));
87
+ }
88
+ return undefined;
89
+ }
11
90
  async function generateUtCode(c) {
12
91
  const autofix = c.autofix === 1;
13
92
  const keepFailedTest = c.keepFailedTest === 1;
93
+ const changedTestFileList = loadChangedTestFiles(c);
14
94
  switch (c.source) {
15
95
  case constants_1.CSVSPLUGIN:
16
96
  try {
17
97
  c.autofix === 1 && (0, stdListener_1.startStdListener)();
18
- await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, c.source, false, c.nugetPackagePath);
98
+ await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, c.source, false, c.nugetPackagePath, changedTestFileList);
19
99
  }
20
100
  catch (error) {
21
101
  console.error("Error in generateUtCode with VS Plugin:", error);
@@ -27,13 +107,13 @@ async function generateUtCode(c) {
27
107
  }
28
108
  break;
29
109
  case constants_1.CSVSCODEPLUGIN:
30
- await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.CSVSCODEPLUGIN, false, c.nugetPackagePath);
110
+ await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.CSVSCODEPLUGIN, false, c.nugetPackagePath, changedTestFileList);
31
111
  break;
32
112
  case constants_1.PIPELINE:
33
- await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.PIPELINE, false, c.nugetPackagePath);
113
+ await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.PIPELINE, false, c.nugetPackagePath, changedTestFileList);
34
114
  break;
35
115
  default:
36
- await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.CSHARPUTGEN, false, c.nugetPackagePath);
116
+ await (0, csharpUtGen_1.generateCsharpUtCode)(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, constants_1.CSHARPUTGEN, false, c.nugetPackagePath, changedTestFileList);
37
117
  break;
38
118
  }
39
119
  }
@@ -46,6 +126,7 @@ async function generateUtBenchmark(c) {
46
126
  const autofix = c.autofix === 1;
47
127
  const keepFailedTest = c.keepFailedTest === 1;
48
128
  await (0, generateBenchmarkReport_1.generateBenchmarkReport)(c.sourceCodePath, autofix, keepFailedTest, c.source);
129
+ console.log(`Generate UT Benchmark report completed for path: ${c.sourceCodePath}, and exit now ${new Date().toISOString()}`);
49
130
  }
50
131
  // generateUtCode({sourceCodePath: "D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Plugins\\Workflows\\Overview\\HttpRequestParser\\Utils\\SqmidHelper.cs", keepFailedTest: 1});
51
132
  // generateUtBenchmarkReport({sourceCodePath: "Q:\\MyProject\\TestTestReport\\TestTestReport\\TestTestReport.csproj", autofix: 1, keepFailedTest: 1, source: CSVSPLUGIN});
@@ -1 +1 @@
1
- {"version":3,"file":"utGenWrapper.js","sourceRoot":"","sources":["../../src/command/utGenWrapper.ts"],"names":[],"mappings":";;AAOA,wCA0BC;AAED,kDAIC;AAED,kDAIC;AA7CD,yDAA8E;AAE9E,kDAAuF;AACvF,kEAAgE;AAChE,oDAA0D;AAC1D,kFAA+E;AAExE,KAAK,UAAU,cAAc,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC;IAChC,MAAM,cAAc,GAAG,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC;IAC9C,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QACf,KAAK,sBAAU;YACX,IAAI,CAAC;gBACD,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,IAAA,8BAAgB,GAAE,CAAC;gBACtC,MAAM,IAAA,kCAAoB,EAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;YAC/H,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;YACpE,CAAC;oBAAS,CAAC;gBACP,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,+BAAiB,EAAC,CAAC;oBACtC,+BAAiB,CAAC,KAAK,EAAE,CAAC;gBAC9B,CAAC;YACL,CAAC;YACD,MAAM;QACV,KAAK,0BAAc;YACf,MAAM,IAAA,kCAAoB,EAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,0BAAc,EAAE,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;YACjI,MAAM;QACV,KAAK,oBAAQ;YACT,MAAM,IAAA,kCAAoB,EAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,oBAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;YAC3H,MAAM;QACV;YACI,MAAM,IAAA,kCAAoB,EAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,uBAAW,EAAE,KAAK,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;YAC9H,MAAM;IACd,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,mBAAmB,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC;IAChC,MAAM,cAAc,GAAG,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC;IAC9C,MAAM,IAAA,sCAAkB,EAAC,CAAC,CAAC,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;AACxE,CAAC;AAEM,KAAK,UAAU,mBAAmB,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC;IAChC,MAAM,cAAc,GAAG,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC;IAC9C,MAAM,IAAA,iDAAuB,EAAC,CAAC,CAAC,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;AACvF,CAAC;AAGD,kNAAkN;AAClN,0KAA0K;AAC1K,+JAA+J","sourcesContent":["import { readLineInterface, startStdListener } from \"../vsPlugin/stdListener\";\r\n\r\nimport { CSHARPUTGEN, CSVSCODEPLUGIN, CSVSPLUGIN, PIPELINE } from \"../types/constants\";\r\nimport { generateBatchTests } from \"../batch/generateCodeTests\";\r\nimport { generateCsharpUtCode } from \"../gen/csharpUtGen\";\r\nimport { generateBenchmarkReport } from '../benchmark/generateBenchmarkReport';\r\n\r\nexport async function generateUtCode(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n switch (c.source) {\r\n case CSVSPLUGIN:\r\n try {\r\n c.autofix === 1 && startStdListener();\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, c.source, false, c.nugetPackagePath);\r\n } catch (error) {\r\n console.error(\"Error in generateUtCode with VS Plugin:\", error);\r\n } finally {\r\n if (c.autofix === 1 && readLineInterface){\r\n readLineInterface.close();\r\n }\r\n }\r\n break;\r\n case CSVSCODEPLUGIN:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, CSVSCODEPLUGIN, false, c.nugetPackagePath);\r\n break;\r\n case PIPELINE:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, PIPELINE, false, c.nugetPackagePath);\r\n break;\r\n default:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, CSHARPUTGEN, false, c.nugetPackagePath);\r\n break;\r\n }\r\n}\r\n\r\nexport async function generateBatchUtCode(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n await generateBatchTests(c.sourceCodePath, autofix, keepFailedTest);\r\n}\r\n\r\nexport async function generateUtBenchmark(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n await generateBenchmarkReport(c.sourceCodePath, autofix, keepFailedTest, c.source);\r\n}\r\n\r\n\r\n// generateUtCode({sourceCodePath: \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Overview\\\\HttpRequestParser\\\\Utils\\\\SqmidHelper.cs\", keepFailedTest: 1});\r\n// generateUtBenchmarkReport({sourceCodePath: \"Q:\\\\MyProject\\\\TestTestReport\\\\TestTestReport\\\\TestTestReport.csproj\", autofix: 1, keepFailedTest: 1, source: CSVSPLUGIN});\r\n// generateUtBenchmarkReport({sourceCodePath: \"Q:\\\\MyProject\\\\TestTestReport\\\\TestTestReport\\\\TestFolder\", autofix: 1, keepFailedTest: 1, source: CSVSPLUGIN});"]}
1
+ {"version":3,"file":"utGenWrapper.js","sourceRoot":"","sources":["../../src/command/utGenWrapper.ts"],"names":[],"mappings":"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","sourcesContent":["import { readLineInterface, startStdListener } from \"../vsPlugin/stdListener\";\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { CSHARPUTGEN, CSVSCODEPLUGIN, CSVSPLUGIN, PIPELINE } from \"../types/constants\";\r\nimport { generateBatchTests } from \"../batch/generateCodeTests\";\r\nimport { generateCsharpUtCode } from \"../gen/csharpUtGen\";\r\nimport { generateBenchmarkReport } from '../benchmark/generateBenchmarkReport';\r\n\r\n/**\r\n * Load changed test files from CLI args or config file\r\n * Priority: config file (changedFilesConfig) > CLI args (changedTestFiles)\r\n * \r\n * @param argv - Command line arguments containing changedFilesConfig and/or changedTestFiles\r\n * @returns Array of changed test file paths (normalized), or undefined if not provided\r\n */\r\nfunction loadChangedTestFiles(argv: any): string[] | undefined {\r\n let changedFiles: string[] = [];\r\n \r\n // Load from config file (higher priority) - changedFilesConfig is string type\r\n if (argv.changedFilesConfig) {\r\n try {\r\n const configPath = path.resolve(argv.changedFilesConfig);\r\n if (!fs.existsSync(configPath)) {\r\n console.warn(`Changed files config not found: ${configPath}`);\r\n } else {\r\n const configContent = fs.readFileSync(configPath, 'utf-8');\r\n const config = JSON.parse(configContent);\r\n if (config.changedTestFiles && Array.isArray(config.changedTestFiles)) {\r\n // Normalize paths\r\n const normalizedFiles = config.changedTestFiles.map((f: string) => path.normalize(f));\r\n changedFiles.push(...normalizedFiles);\r\n console.log(`Loaded ${normalizedFiles.length} changed test files from config: ${configPath}`); \r\n return Array.from(new Set(changedFiles));\r\n }\r\n }\r\n } catch (err: any) {\r\n console.warn(`Failed to load changed files config: ${err.message}`);\r\n }\r\n }\r\n \r\n // Load from CLI args (changedTestFiles is array type, each element is string)\r\n if (argv.changedTestFiles && Array.isArray(argv.changedTestFiles)) {\r\n // Normalize paths and remove duplicates\r\n const cliFiles = argv.changedTestFiles as string[];\r\n const normalizedCliFiles = cliFiles.map((f: string) => path.normalize(f));\r\n const uniqueCliFiles = normalizedCliFiles.filter((f: string) => !changedFiles.includes(f));\r\n changedFiles.push(...uniqueCliFiles);\r\n console.log(`Loaded ${uniqueCliFiles.length} changed test files from CLI args (--changedTestFiles)`);\r\n\r\n return Array.from(new Set(changedFiles));\r\n }\r\n \r\n return undefined;\r\n}\r\n\r\nexport async function generateUtCode(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n const changedTestFileList = loadChangedTestFiles(c);\r\n \r\n switch (c.source) {\r\n case CSVSPLUGIN:\r\n try {\r\n c.autofix === 1 && startStdListener();\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, c.source, false, c.nugetPackagePath, changedTestFileList);\r\n } catch (error) {\r\n console.error(\"Error in generateUtCode with VS Plugin:\", error);\r\n } finally {\r\n if (c.autofix === 1 && readLineInterface){\r\n readLineInterface.close();\r\n }\r\n }\r\n break;\r\n case CSVSCODEPLUGIN:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, CSVSCODEPLUGIN, false, c.nugetPackagePath, changedTestFileList);\r\n break;\r\n case PIPELINE:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, PIPELINE, false, c.nugetPackagePath, changedTestFileList);\r\n break;\r\n default:\r\n await generateCsharpUtCode(c.sourceCodePath, c.testCodePath, autofix, keepFailedTest, CSHARPUTGEN, false, c.nugetPackagePath, changedTestFileList);\r\n break;\r\n }\r\n}\r\n\r\nexport async function generateBatchUtCode(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n await generateBatchTests(c.sourceCodePath, autofix, keepFailedTest);\r\n}\r\n\r\nexport async function generateUtBenchmark(c) {\r\n const autofix = c.autofix === 1;\r\n const keepFailedTest = c.keepFailedTest === 1;\r\n await generateBenchmarkReport(c.sourceCodePath, autofix, keepFailedTest, c.source);\r\n console.log(`Generate UT Benchmark report completed for path: ${c.sourceCodePath}, and exit now ${new Date().toISOString()}`);\r\n}\r\n\r\n\r\n// generateUtCode({sourceCodePath: \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Overview\\\\HttpRequestParser\\\\Utils\\\\SqmidHelper.cs\", keepFailedTest: 1});\r\n// generateUtBenchmarkReport({sourceCodePath: \"Q:\\\\MyProject\\\\TestTestReport\\\\TestTestReport\\\\TestTestReport.csproj\", autofix: 1, keepFailedTest: 1, source: CSVSPLUGIN});\r\n// generateUtBenchmarkReport({sourceCodePath: \"Q:\\\\MyProject\\\\TestTestReport\\\\TestTestReport\\\\TestFolder\", autofix: 1, keepFailedTest: 1, source: CSVSPLUGIN});"]}
@@ -1,4 +1,4 @@
1
1
  import { GenResult } from "../types/genResult";
2
- export declare function autoFixTestCode(prompts: any[], sourceCodePath: string, testCode: string, testProjectPath: string, testFilePath: string, testFramework: string, isXapCode: boolean, isVsPlugin: boolean, retryTimes?: number, isBenchmark?: boolean): Promise<GenResult>;
3
- export declare function generateAutoFixCode(prompts: any[], generatedCode: string, errorMessage: string, isBuildFailure: boolean, testFilePath: string, testFramework: string, isXapCode: boolean): Promise<string>;
2
+ export declare function autoFixTestCode(prompts: any[], sourceCodePath: string, sourceCode: string, dependency: string, testCode: string, testProjectPath: string, testFilePath: string, testFramework: string, isXapCode: boolean, isVsPlugin: boolean, testFileExist: boolean, keepFailedTests: boolean, insertedRanges?: [number, number][], retryTimes?: number, isBenchmark?: boolean, originalTestLength?: number): Promise<GenResult>;
3
+ export declare function generateAutoFixCode(prompts: any[], sourceCodePath: string, sourceCode: string, dependency: string, generatedCode: string, errorMessage: string, isBuildFailure: boolean, testFilePath: string, testFramework: string, isXapCode: boolean, testFileExist: boolean): Promise<string>;
4
4
  export declare function autoRetryTestCode(prompts: any[], sourceCodePath: string, testCode: string, testProjectPath: string, testFilePath: string, testFramework: string, isXapCode: boolean, retryTimes?: number): Promise<GenResult>;
@@ -5,16 +5,15 @@ exports.generateAutoFixCode = generateAutoFixCode;
5
5
  exports.autoRetryTestCode = autoRetryTestCode;
6
6
  const checkCodeSyntax_1 = require("../analyze/checkCodeSyntax");
7
7
  const ensureValidLLMResponse_1 = require("./ensureValidLLMResponse");
8
- const postGenProcess_1 = require("./postGen/postGenProcess");
9
8
  const preparePrompt_1 = require("../llm/preparePrompt");
10
9
  const verifyBuildErrorCausedFile_1 = require("../utils/verifyBuildErrorCausedFile");
11
- const verifyTestCode_1 = require("../utils/verifyTestCode");
12
- const getVsPluginVerifyResult_1 = require("../vsPlugin/getVsPluginVerifyResult");
10
+ const verifyGeneratedCode_1 = require("../utils/verifyGeneratedCode");
11
+ const removeFailedTestMethods_1 = require("../utils/removeFailedTestMethods");
13
12
  const writeGenCode_1 = require("../utils/writeGenCode");
14
13
  const fileUtils_1 = require("../utils/fileUtils");
15
14
  const writeFailedVerifyResult_1 = require("../utils/writeFailedVerifyResult");
16
15
  const getCodeStructurePath_1 = require("../utils/getCodeStructurePath");
17
- async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, retryTimes = 3, isBenchmark = false) {
16
+ async function autoFixTestCode(prompts, sourceCodePath, sourceCode, dependency, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, testFileExist, keepFailedTests, insertedRanges = undefined, retryTimes = 3, isBenchmark = false, originalTestLength = 0) {
18
17
  const startTime = Date.now();
19
18
  let generatedCode = testCode;
20
19
  let testResult;
@@ -29,9 +28,9 @@ async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPat
29
28
  // for case: generatedCode is invalid, just retry instead of auto fix process
30
29
  if (!generatedCode) {
31
30
  console.error(`Generated code is invalid, try to regenerate. \nGenerated code: \n${generatedCode}`);
32
- generatedCode = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(prompts, testFramework, isXapCode);
33
- // extract valid code from LLM response
34
- generatedCode = (0, postGenProcess_1.postGenProcess)(generatedCode, testFramework, isXapCode);
31
+ const llmResult = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(prompts, testFramework, isXapCode, testFileExist, testFilePath, false, 3, sourceCode);
32
+ generatedCode = llmResult?.testCode;
33
+ insertedRanges = llmResult?.insertedRanges;
35
34
  continue;
36
35
  }
37
36
  // analyze generated code issue before verify: build, because build will cost much time.
@@ -39,20 +38,21 @@ async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPat
39
38
  if (syntaxResult.success) {
40
39
  // if generated code passed the syntax check, verify the generated test code
41
40
  // const { success, message, buildErrors, vsTestResult } = await verifyTestCode(generatedCode, testProjectPath);
42
- const verifyResult = await verifyGeneratedCode(generatedCode, testProjectPath, testFilePath, isVsPlugin);
41
+ const verifyResult = await (0, verifyGeneratedCode_1.verifyGeneratedCode)(generatedCode, testProjectPath, testFilePath, isVsPlugin);
43
42
  errorMessage = verifyResult.message;
44
43
  testResult = verifyResult.testResult;
45
44
  buildResult = verifyResult.buildErrors;
46
45
  isBuildFailure = !testResult;
47
- // if build errors caused by other code files instead of generate test code, abort generation
48
- const validBuildError = (0, verifyBuildErrorCausedFile_1.verifyBuildErrorCausedFile)(testFilePath, buildResult);
49
- if (!validBuildError) {
50
- console.error("Due to build errors caused by other code files, abort generation, please fix it first.");
51
- return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
52
- }
53
46
  if (verifyResult.success) {
54
- console.log("XapUt code generated successfully");
55
- return { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
47
+ // Check if new code length is greater than original test length
48
+ const currentCode = (0, fileUtils_1.readTestCode)(testFilePath);
49
+ if (originalTestLength > 0 && currentCode && currentCode.length <= originalTestLength) {
50
+ console.error("Generated code length is not greater than original test code length, treating as failure.");
51
+ }
52
+ else {
53
+ console.log("XapUt code generated successfully");
54
+ return { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
55
+ }
56
56
  }
57
57
  console.error("Failed to verifyTestCode, error:", errorMessage);
58
58
  }
@@ -61,6 +61,21 @@ async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPat
61
61
  errorMessage = syntaxResult.message;
62
62
  console.error("Failed to check the generated UT code syntax, error:", errorMessage);
63
63
  }
64
+ // if errors caused by other code files instead of generate test code, abort generation
65
+ const validBuildError = (0, verifyBuildErrorCausedFile_1.verifyBuildErrorCausedFile)(testFilePath, buildResult);
66
+ if (!validBuildError) {
67
+ console.error("Due to errors caused by other code files, abort generation, please fix it first.");
68
+ return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
69
+ }
70
+ // if errors are caused by original test lines (not inserted lines), abort generation
71
+ // Only check on first iteration since insertedRanges becomes stale after code is modified
72
+ if (i === 0 && insertedRanges && insertedRanges.length > 0) {
73
+ const isErrorInInsertedLines = verifyBuildErrorCausedLines(buildResult, insertedRanges);
74
+ if (!isErrorInInsertedLines) {
75
+ console.error("Errors are caused by original test code lines, not by inserted code. Abort generation.");
76
+ return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
77
+ }
78
+ }
64
79
  isBenchmark && (0, writeFailedVerifyResult_1.writeFailedVerifyResult)(sourceCodePath, i, sourceCodeProjectPath, errorMessage, !testResult);
65
80
  // keep test failed tast cases in test file automatically
66
81
  // if (!isBuildFailure && vsTestRes.passed !== 0) {
@@ -69,7 +84,7 @@ async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPat
69
84
  // return { success: true, testCode: generatedCode };
70
85
  // }
71
86
  if (i === retryTimes) {
72
- console.error(`Failed to generate ut code after ${retryTimes} attempts.`);
87
+ console.log(`Autofix failed after ${retryTimes} attempts, will try to remove failed test methods...`);
73
88
  break;
74
89
  }
75
90
  // case: vs plugin no response or msbuild/vstest failed.
@@ -77,32 +92,73 @@ async function autoFixTestCode(prompts, sourceCodePath, testCode, testProjectPat
77
92
  console.error("!!!Verify process failed, retrying...");
78
93
  continue;
79
94
  }
80
- generatedCode = await generateAutoFixCode(prompts, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode);
95
+ generatedCode = await generateAutoFixCode(prompts, sourceCodePath, sourceCode, dependency, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode, testFileExist);
81
96
  }
82
- console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);
97
+ // Try to remove failed test methods and return success if possible (only when keepFailedTests is false)
98
+ if (!keepFailedTests) {
99
+ const removeResult = await (0, removeFailedTestMethods_1.removeFailedTestMethods)(generatedCode, testFilePath, testProjectPath, sourceCodePath, buildResult, testResult, isVsPlugin, originalTestLength);
100
+ if (removeResult) {
101
+ if (removeResult.success) {
102
+ // Check if there are still test methods left in the code
103
+ const remainingCode = (0, fileUtils_1.readTestCode)(testFilePath);
104
+ const hasTestMethods = /\[(TestMethod|Test|Fact|Theory)\]/i.test(remainingCode || '');
105
+ if (!hasTestMethods) {
106
+ console.error("No test methods remaining after removing failed tests.");
107
+ return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
108
+ }
109
+ }
110
+ console.log(`Remove failed test methods ${removeResult.success ? 'succeeded' : 'failed'}.`);
111
+ return removeResult;
112
+ }
113
+ }
114
+ console.error("Failed to generate valid test code after all attempts.");
83
115
  return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };
84
116
  }
85
117
  catch (error) {
86
118
  console.error("Error during auto-fix process:", error);
87
119
  return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };
88
120
  }
121
+ finally {
122
+ console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);
123
+ }
89
124
  }
90
- async function verifyGeneratedCode(generatedCode, testProjectPath, testFilePath, isVsPlugin = false) {
91
- if (isVsPlugin) {
92
- const vsVerifyResult = await (0, getVsPluginVerifyResult_1.verifyTestCodeByVsPlugin)(testFilePath);
93
- return vsVerifyResult;
125
+ /**
126
+ * Verify if build errors are caused by the inserted lines.
127
+ * Returns true if all build errors are within the inserted ranges (meaning they are caused by new code).
128
+
129
+ * Returns false if any build error is outside the inserted ranges (meaning it's caused by original code).
130
+ */
131
+ function verifyBuildErrorCausedLines(buildResult, insertedRanges) {
132
+ if (!buildResult || !buildResult.errors || buildResult.errors.length === 0) {
133
+ return true; // No build errors
94
134
  }
95
- else {
96
- // verifyResult: { success, message, buildErrors, vsTestResult }
97
- const verifyResult = await (0, verifyTestCode_1.verifyTestCode)(generatedCode, testProjectPath);
98
- return verifyResult;
135
+ for (const error of buildResult.errors) {
136
+ const errorLine = error.line;
137
+ if (!errorLine)
138
+ continue;
139
+ let isInInsertedRange = false;
140
+ for (const [start, end] of insertedRanges) {
141
+ if (errorLine >= start && errorLine <= end) {
142
+ isInInsertedRange = true;
143
+ break;
144
+ }
145
+ }
146
+ if (!isInInsertedRange) {
147
+ // This error is in original code, not in inserted code
148
+ console.error(`Build error at line ${errorLine} is in original test code, not in inserted code.`);
149
+ return false;
150
+ }
99
151
  }
152
+ return true; // All errors are in inserted ranges
100
153
  }
101
- async function generateAutoFixCode(prompts, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode) {
154
+ async function generateAutoFixCode(prompts, sourceCodePath, sourceCode, dependency, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode, testFileExist) {
102
155
  console.log("start auto-fix process...");
103
- const autofixPrompt = (0, preparePrompt_1.prepareUtAutoFixPrompt)(prompts, generatedCode, errorMessage, isBuildFailure);
156
+ const autofixPrompt = testFileExist
157
+ ? (0, preparePrompt_1.prepareMoreUtAutoFixPrompt)(sourceCode, dependency, generatedCode, errorMessage, isBuildFailure, isXapCode)
158
+ : (0, preparePrompt_1.prepareUtAutoFixPrompt)(prompts, generatedCode, errorMessage, isBuildFailure);
104
159
  // get valid code from LLM response with retry
105
- const newGeneratedCode = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(autofixPrompt, testFramework, isXapCode);
160
+ const llmResult = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(autofixPrompt, testFramework, isXapCode, false, testFilePath, true, 3, sourceCode);
161
+ const newGeneratedCode = llmResult?.testCode;
106
162
  // if generate code is valid, write test code to test project
107
163
  !!newGeneratedCode && (0, fileUtils_1.writeTestCode)(newGeneratedCode, testFilePath);
108
164
  return newGeneratedCode;
@@ -119,7 +175,8 @@ async function autoRetryTestCode(prompts, sourceCodePath, testCode, testProjectP
119
175
  }
120
176
  const autofixPrompt = prompts;
121
177
  // get valid code from LLM response
122
- generatedCode = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(autofixPrompt, testFramework, isXapCode);
178
+ const llmResult = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(autofixPrompt, testFramework, isXapCode, false, testFilePath, true);
179
+ generatedCode = llmResult?.testCode;
123
180
  // write test code to test project
124
181
  (0, fileUtils_1.writeTestCode)(generatedCode, testFilePath);
125
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"autoFix.js","sourceRoot":"","sources":["../../src/gen/autoFix.ts"],"names":[],"mappings":";;AAcA,0CA8FC;AAkBD,kDAmBC;AAID,8CA8BC;AAjLD,gEAA6D;AAC7D,qEAAkE;AAClE,6DAA0D;AAC1D,wDAA8D;AAC9D,oFAAiF;AACjF,4DAAyD;AACzD,iFAA+E;AAC/E,wDAAqD;AACrD,kDAAmD;AACnD,8EAA2E;AAC3E,wEAA4E;AAErE,KAAK,UAAU,eAAe,CACjC,OAAc,EACd,cAAsB,EACtB,QAAgB,EAChB,eAAuB,EACvB,YAAoB,EACpB,aAAqB,EACrB,SAAkB,EAClB,UAAmB,EACnB,aAAqB,CAAC,EACtB,cAAuB,KAAK;IAE5B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,aAAa,GAAG,QAAQ,CAAC;IAC7B,IAAI,UAAU,CAAC;IACf,IAAI,WAAW,CAAC;IAChB,IAAI,YAAY,CAAC;IACjB,IAAI,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC;QACD,MAAM,qBAAqB,GAAG,IAAA,kDAA2B,EAAC,cAAc,CAAC,CAAC;QAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,2DAA2D;YAC3D,WAAW,IAAI,IAAA,2BAAY,EAAC,cAAc,EAAE,aAAa,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAC;YAErF,6EAA6E;YAC7E,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,qEAAqE,aAAa,EAAE,CAAC,CAAC;gBACpG,aAAa,GAAG,MAAM,IAAA,+CAAsB,EAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;gBAChF,uCAAuC;gBACvC,aAAa,GAAG,IAAA,+BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;gBACxE,SAAS;YACb,CAAC;YAED,wFAAwF;YACxF,MAAM,YAAY,GAAG,MAAM,IAAA,iCAAe,EAAC,YAAY,CAAC,CAAC;YACzD,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACvB,4EAA4E;gBAC5E,gHAAgH;gBAChH,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;gBACzG,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC;gBACpC,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC;gBACrC,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC;gBACvC,cAAc,GAAG,CAAC,UAAU,CAAC;gBAE7B,6FAA6F;gBAC7F,MAAM,eAAe,GAAG,IAAA,uDAA0B,EAAC,YAAY,EAAE,WAAW,CAAC,CAAC;gBAC9E,IAAI,CAAC,eAAe,EAAE,CAAC;oBACnB,OAAO,CAAC,KAAK,CAAC,wFAAwF,CAAC,CAAC;oBACxG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;gBACpH,CAAC;gBAED,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;oBACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;gBACnH,CAAC;gBAED,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,YAAY,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACJ,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC;gBACvC,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC;gBACpC,OAAO,CAAC,KAAK,CAAC,sDAAsD,EAAE,YAAY,CAAC,CAAC;YACxF,CAAC;YAED,WAAW,IAAI,IAAA,iDAAuB,EAAC,cAAc,EAAE,CAAC,EAAE,qBAAqB,EAAE,YAAY,EAAE,CAAC,UAAU,CAAC,CAAC;YAC5G,yDAAyD;YACzD,mDAAmD;YACnD,4DAA4D;YAC5D,gEAAgE;YAChE,yDAAyD;YACzD,IAAI;YAEJ,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,oCAAoC,UAAU,YAAY,CAAC,CAAC;gBAC1E,MAAM;YACV,CAAC;YAED,wDAAwD;YACxD,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;gBACvD,SAAS;YACb,CAAC;YAED,aAAa,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;QAC5I,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;QAExE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;IACpH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAEhI,CAAC;AACL,CAAC;AAED,KAAK,UAAU,mBAAmB,CAC9B,aAAqB,EACrB,eAAuB,EACvB,YAAoB,EACpB,aAAsB,KAAK;IAE3B,IAAI,UAAU,EAAE,CAAC;QACb,MAAM,cAAc,GAAG,MAAM,IAAA,kDAAwB,EAAC,YAAY,CAAC,CAAC;QACpE,OAAO,cAAc,CAAC;IAC1B,CAAC;SAAM,CAAC;QACJ,gEAAgE;QAChE,MAAM,YAAY,GAAG,MAAM,IAAA,+BAAc,EAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QAC1E,OAAO,YAAY,CAAC;IACxB,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,mBAAmB,CACrC,OAAc,EACd,aAAqB,EACrB,YAAoB,EACpB,cAAuB,EACvB,YAAoB,EACpB,aAAqB,EACrB,SAAkB;IAElB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,IAAA,sCAAsB,EAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;IAEnG,8CAA8C;IAC9C,MAAM,gBAAgB,GAAG,MAAM,IAAA,+CAAsB,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IAE/F,6DAA6D;IAC7D,CAAC,CAAC,gBAAgB,IAAI,IAAA,yBAAa,EAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;IAEpE,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAGD,yBAAyB;AAClB,KAAK,UAAU,iBAAiB,CACnC,OAAc,EACd,cAAsB,EACtB,QAAgB,EAChB,eAAuB,EACvB,YAAoB,EACpB,aAAqB,EACrB,SAAkB,EAClB,aAAqB,CAAC;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,aAAa,GAAG,QAAQ,CAAC;IAC7B,IAAI,SAAS,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,uCAAuC,UAAU,YAAY,CAAC,CAAC;YAC7E,MAAM;QACV,CAAC;QAED,MAAM,aAAa,GAAG,OAAO,CAAC;QAC9B,mCAAmC;QACnC,aAAa,GAAG,MAAM,IAAA,+CAAsB,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;QACtF,kCAAkC;QAClC,IAAA,yBAAa,EAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;IAExE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAClJ,CAAC","sourcesContent":["import { GenResult } from \"../types/genResult\";\r\nimport { VerifyResult } from \"../types/verifyResult\";\r\nimport { checkCodeSyntax } from \"../analyze/checkCodeSyntax\";\r\nimport { ensureValidLLMResponse } from \"./ensureValidLLMResponse\";\r\nimport { postGenProcess } from \"./postGen/postGenProcess\";\r\nimport { prepareUtAutoFixPrompt } from \"../llm/preparePrompt\";\r\nimport { verifyBuildErrorCausedFile } from \"../utils/verifyBuildErrorCausedFile\";\r\nimport { verifyTestCode } from \"../utils/verifyTestCode\";\r\nimport { verifyTestCodeByVsPlugin } from \"../vsPlugin/getVsPluginVerifyResult\";\r\nimport { writeGenCode } from \"../utils/writeGenCode\";\r\nimport { writeTestCode } from \"../utils/fileUtils\";\r\nimport { writeFailedVerifyResult } from \"../utils/writeFailedVerifyResult\";\r\nimport { getSourceFileCsprojFilePath } from \"../utils/getCodeStructurePath\";\r\n\r\nexport async function autoFixTestCode(\r\n prompts: any[],\r\n sourceCodePath: string,\r\n testCode: string,\r\n testProjectPath: string,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n isVsPlugin: boolean,\r\n retryTimes: number = 3,\r\n isBenchmark: boolean = false\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n let generatedCode = testCode;\r\n let testResult;\r\n let buildResult;\r\n let errorMessage;\r\n let isBuildFailure = true;\r\n try {\r\n const sourceCodeProjectPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n for (let i = 0; i <= retryTimes; i++) {\r\n // write generated code, to review and improve code quality\r\n isBenchmark && writeGenCode(sourceCodePath, generatedCode, i, sourceCodeProjectPath);\r\n\r\n // for case: generatedCode is invalid, just retry instead of auto fix process\r\n if (!generatedCode) {\r\n console.error(`Generated code is invalid, try to regenerate. \\nGenerated code: \\n${generatedCode}`);\r\n generatedCode = await ensureValidLLMResponse(prompts, testFramework, isXapCode);\r\n // extract valid code from LLM response\r\n generatedCode = postGenProcess(generatedCode, testFramework, isXapCode);\r\n continue;\r\n }\r\n\r\n // analyze generated code issue before verify: build, because build will cost much time.\r\n const syntaxResult = await checkCodeSyntax(testFilePath);\r\n if (syntaxResult.success) {\r\n // if generated code passed the syntax check, verify the generated test code\r\n // const { success, message, buildErrors, vsTestResult } = await verifyTestCode(generatedCode, testProjectPath);\r\n const verifyResult = await verifyGeneratedCode(generatedCode, testProjectPath, testFilePath, isVsPlugin);\r\n errorMessage = verifyResult.message;\r\n testResult = verifyResult.testResult;\r\n buildResult = verifyResult.buildErrors;\r\n isBuildFailure = !testResult;\r\n\r\n // if build errors caused by other code files instead of generate test code, abort generation\r\n const validBuildError = verifyBuildErrorCausedFile(testFilePath, buildResult);\r\n if (!validBuildError) {\r\n console.error(\"Due to build errors caused by other code files, abort generation, please fix it first.\");\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n\r\n if (verifyResult.success) {\r\n console.log(\"XapUt code generated successfully\");\r\n return { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n\r\n console.error(\"Failed to verifyTestCode, error:\", errorMessage);\r\n } else {\r\n buildResult = syntaxResult.buildErrors;\r\n errorMessage = syntaxResult.message;\r\n console.error(\"Failed to check the generated UT code syntax, error:\", errorMessage);\r\n }\r\n\r\n isBenchmark && writeFailedVerifyResult(sourceCodePath, i, sourceCodeProjectPath, errorMessage, !testResult);\r\n // keep test failed tast cases in test file automatically\r\n // if (!isBuildFailure && vsTestRes.passed !== 0) {\r\n // console.log(\"remove failed test cases in test file\");\r\n // removeFailedTestCasesInTestFile(vsTestRes, testCodePath);\r\n // return { success: true, testCode: generatedCode };\r\n // }\r\n\r\n if (i === retryTimes) {\r\n console.error(`Failed to generate ut code after ${retryTimes} attempts.`);\r\n break;\r\n }\r\n\r\n // case: vs plugin no response or msbuild/vstest failed.\r\n if (!buildResult && !testResult) {\r\n console.error(\"!!!Verify process failed, retrying...\");\r\n continue;\r\n }\r\n\r\n generatedCode = await generateAutoFixCode(prompts, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode);\r\n }\r\n\r\n console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);\r\n\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n } catch (error) {\r\n console.error(\"Error during auto-fix process:\", error);\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n\r\n }\r\n}\r\n\r\nasync function verifyGeneratedCode(\r\n generatedCode: string,\r\n testProjectPath: string,\r\n testFilePath: string,\r\n isVsPlugin: boolean = false\r\n): Promise<VerifyResult> {\r\n if (isVsPlugin) {\r\n const vsVerifyResult = await verifyTestCodeByVsPlugin(testFilePath);\r\n return vsVerifyResult;\r\n } else {\r\n // verifyResult: { success, message, buildErrors, vsTestResult }\r\n const verifyResult = await verifyTestCode(generatedCode, testProjectPath);\r\n return verifyResult;\r\n }\r\n}\r\n\r\nexport async function generateAutoFixCode(\r\n prompts: any[],\r\n generatedCode: string,\r\n errorMessage: string,\r\n isBuildFailure: boolean,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean\r\n): Promise<string> {\r\n console.log(\"start auto-fix process...\");\r\n const autofixPrompt = prepareUtAutoFixPrompt(prompts, generatedCode, errorMessage, isBuildFailure);\r\n\r\n // get valid code from LLM response with retry\r\n const newGeneratedCode = await ensureValidLLMResponse(autofixPrompt, testFramework, isXapCode);\r\n\r\n // if generate code is valid, write test code to test project\r\n !!newGeneratedCode && writeTestCode(newGeneratedCode, testFilePath);\r\n\r\n return newGeneratedCode;\r\n}\r\n\r\n\r\n// use for quick dev test\r\nexport async function autoRetryTestCode(\r\n prompts: any[],\r\n sourceCodePath: string,\r\n testCode: string,\r\n testProjectPath: string,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n retryTimes: number = 3\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n let generatedCode = testCode;\r\n let vsTestRes;\r\n for (let i = 0; i <= retryTimes; i++) {\r\n if (i === retryTimes) {\r\n console.error(`Failed to generate XapUt code after ${retryTimes} attempts.`);\r\n break;\r\n }\r\n\r\n const autofixPrompt = prompts;\r\n // get valid code from LLM response\r\n generatedCode = await ensureValidLLMResponse(autofixPrompt, testFramework, isXapCode);\r\n // write test code to test project\r\n writeTestCode(generatedCode, testFilePath);\r\n }\r\n\r\n console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);\r\n\r\n return { success: true, testFilePath: testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: vsTestRes };\r\n}"]}
1
+ {"version":3,"file":"autoFix.js","sourceRoot":"","sources":["../../src/gen/autoFix.ts"],"names":[],"mappings":"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","sourcesContent":["import { GenResult } from \"../types/genResult\";\r\nimport { checkCodeSyntax } from \"../analyze/checkCodeSyntax\";\r\nimport { ensureValidLLMResponse } from \"./ensureValidLLMResponse\";\r\nimport { prepareUtAutoFixPrompt, prepareMoreUtAutoFixPrompt } from \"../llm/preparePrompt\";\r\nimport { verifyBuildErrorCausedFile } from \"../utils/verifyBuildErrorCausedFile\";\r\nimport { verifyGeneratedCode } from \"../utils/verifyGeneratedCode\";\r\nimport { removeFailedTestMethods } from \"../utils/removeFailedTestMethods\";\r\nimport { writeGenCode } from \"../utils/writeGenCode\";\r\nimport { writeTestCode, readTestCode } from \"../utils/fileUtils\";\r\nimport { writeFailedVerifyResult } from \"../utils/writeFailedVerifyResult\";\r\nimport { getSourceFileCsprojFilePath } from \"../utils/getCodeStructurePath\";\r\n\r\nexport async function autoFixTestCode(\r\n prompts: any[],\r\n sourceCodePath: string,\r\n sourceCode: string,\r\n dependency: string,\r\n testCode: string,\r\n testProjectPath: string,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n isVsPlugin: boolean,\r\n testFileExist: boolean,\r\n keepFailedTests: boolean,\r\n insertedRanges: [number, number][] = undefined,\r\n retryTimes: number = 3,\r\n isBenchmark: boolean = false,\r\n originalTestLength: number = 0\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n let generatedCode = testCode;\r\n let testResult;\r\n let buildResult;\r\n let errorMessage;\r\n let isBuildFailure = true;\r\n try {\r\n const sourceCodeProjectPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n for (let i = 0; i <= retryTimes; i++) {\r\n // write generated code, to review and improve code quality\r\n isBenchmark && writeGenCode(sourceCodePath, generatedCode, i, sourceCodeProjectPath);\r\n\r\n // for case: generatedCode is invalid, just retry instead of auto fix process\r\n if (!generatedCode) {\r\n console.error(`Generated code is invalid, try to regenerate. \\nGenerated code: \\n${generatedCode}`);\r\n const llmResult = await ensureValidLLMResponse(prompts, testFramework, isXapCode, testFileExist, testFilePath, false, 3, sourceCode);\r\n generatedCode = llmResult?.testCode;\r\n insertedRanges = llmResult?.insertedRanges;\r\n continue;\r\n }\r\n\r\n // analyze generated code issue before verify: build, because build will cost much time.\r\n const syntaxResult = await checkCodeSyntax(testFilePath);\r\n if (syntaxResult.success) {\r\n // if generated code passed the syntax check, verify the generated test code\r\n // const { success, message, buildErrors, vsTestResult } = await verifyTestCode(generatedCode, testProjectPath);\r\n const verifyResult = await verifyGeneratedCode(generatedCode, testProjectPath, testFilePath, isVsPlugin);\r\n errorMessage = verifyResult.message;\r\n testResult = verifyResult.testResult;\r\n buildResult = verifyResult.buildErrors;\r\n isBuildFailure = !testResult;\r\n\r\n if (verifyResult.success) {\r\n // Check if new code length is greater than original test length\r\n const currentCode = readTestCode(testFilePath);\r\n if (originalTestLength > 0 && currentCode && currentCode.length <= originalTestLength) {\r\n console.error(\"Generated code length is not greater than original test code length, treating as failure.\");\r\n } else {\r\n console.log(\"XapUt code generated successfully\");\r\n return { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n }\r\n\r\n console.error(\"Failed to verifyTestCode, error:\", errorMessage);\r\n } else {\r\n buildResult = syntaxResult.buildErrors;\r\n errorMessage = syntaxResult.message;\r\n console.error(\"Failed to check the generated UT code syntax, error:\", errorMessage);\r\n }\r\n\r\n // if errors caused by other code files instead of generate test code, abort generation\r\n const validBuildError = verifyBuildErrorCausedFile(testFilePath, buildResult);\r\n if (!validBuildError) {\r\n console.error(\"Due to errors caused by other code files, abort generation, please fix it first.\");\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n\r\n // if errors are caused by original test lines (not inserted lines), abort generation\r\n // Only check on first iteration since insertedRanges becomes stale after code is modified\r\n if (i === 0 && insertedRanges && insertedRanges.length > 0) {\r\n const isErrorInInsertedLines = verifyBuildErrorCausedLines(buildResult, insertedRanges);\r\n if (!isErrorInInsertedLines) {\r\n console.error(\"Errors are caused by original test code lines, not by inserted code. Abort generation.\");\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n }\r\n\r\n isBenchmark && writeFailedVerifyResult(sourceCodePath, i, sourceCodeProjectPath, errorMessage, !testResult);\r\n // keep test failed tast cases in test file automatically\r\n // if (!isBuildFailure && vsTestRes.passed !== 0) {\r\n // console.log(\"remove failed test cases in test file\");\r\n // removeFailedTestCasesInTestFile(vsTestRes, testCodePath);\r\n // return { success: true, testCode: generatedCode };\r\n // }\r\n\r\n if (i === retryTimes) {\r\n console.log(`Autofix failed after ${retryTimes} attempts, will try to remove failed test methods...`);\r\n break;\r\n }\r\n\r\n // case: vs plugin no response or msbuild/vstest failed.\r\n if (!buildResult && !testResult) {\r\n console.error(\"!!!Verify process failed, retrying...\");\r\n continue;\r\n }\r\n\r\n generatedCode = await generateAutoFixCode(prompts, sourceCodePath, sourceCode, dependency, generatedCode, errorMessage, isBuildFailure, testFilePath, testFramework, isXapCode, testFileExist);\r\n }\r\n\r\n // Try to remove failed test methods and return success if possible (only when keepFailedTests is false)\r\n if (!keepFailedTests) {\r\n const removeResult = await removeFailedTestMethods(generatedCode, testFilePath, testProjectPath, sourceCodePath, buildResult, testResult, isVsPlugin, originalTestLength);\r\n if (removeResult) {\r\n if (removeResult.success) {\r\n // Check if there are still test methods left in the code\r\n const remainingCode = readTestCode(testFilePath);\r\n const hasTestMethods = /\\[(TestMethod|Test|Fact|Theory)\\]/i.test(remainingCode || '');\r\n if (!hasTestMethods) {\r\n console.error(\"No test methods remaining after removing failed tests.\");\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n }\r\n }\r\n console.log(`Remove failed test methods ${removeResult.success ? 'succeeded' : 'failed'}.`);\r\n return removeResult;\r\n }\r\n }\r\n\r\n console.error(\"Failed to generate valid test code after all attempts.\");\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult, testResult };\r\n } catch (error) {\r\n console.error(\"Error during auto-fix process:\", error);\r\n return { success: false, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n } finally {\r\n console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);\r\n }\r\n}\r\n\r\n/**\r\n * Verify if build errors are caused by the inserted lines.\r\n * Returns true if all build errors are within the inserted ranges (meaning they are caused by new code).\r\n\r\n * Returns false if any build error is outside the inserted ranges (meaning it's caused by original code).\r\n */\r\nfunction verifyBuildErrorCausedLines(buildResult: any, insertedRanges: [number, number][]): boolean {\r\n if (!buildResult || !buildResult.errors || buildResult.errors.length === 0) {\r\n return true; // No build errors\r\n }\r\n\r\n for (const error of buildResult.errors) {\r\n const errorLine = error.line;\r\n if (!errorLine) continue;\r\n\r\n let isInInsertedRange = false;\r\n for (const [start, end] of insertedRanges) {\r\n if (errorLine >= start && errorLine <= end) {\r\n isInInsertedRange = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!isInInsertedRange) {\r\n // This error is in original code, not in inserted code\r\n console.error(`Build error at line ${errorLine} is in original test code, not in inserted code.`);\r\n return false;\r\n }\r\n }\r\n\r\n return true; // All errors are in inserted ranges\r\n}\r\n\r\n\r\nexport async function generateAutoFixCode(\r\n prompts: any[],\r\n sourceCodePath: string,\r\n sourceCode: string,\r\n dependency: string,\r\n generatedCode: string,\r\n errorMessage: string,\r\n isBuildFailure: boolean,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n testFileExist: boolean\r\n): Promise<string> {\r\n console.log(\"start auto-fix process...\");\r\n const autofixPrompt = testFileExist \r\n ? prepareMoreUtAutoFixPrompt(sourceCode, dependency, generatedCode, errorMessage, isBuildFailure, isXapCode)\r\n : prepareUtAutoFixPrompt(prompts, generatedCode, errorMessage, isBuildFailure);\r\n\r\n // get valid code from LLM response with retry\r\n const llmResult = await ensureValidLLMResponse(autofixPrompt, testFramework, isXapCode, false, testFilePath, true, 3, sourceCode);\r\n const newGeneratedCode = llmResult?.testCode;\r\n\r\n // if generate code is valid, write test code to test project\r\n !!newGeneratedCode && writeTestCode(newGeneratedCode, testFilePath);\r\n\r\n return newGeneratedCode;\r\n}\r\n\r\n\r\n// use for quick dev test\r\nexport async function autoRetryTestCode(\r\n prompts: any[],\r\n sourceCodePath: string,\r\n testCode: string,\r\n testProjectPath: string,\r\n testFilePath: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n retryTimes: number = 3\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n let generatedCode = testCode;\r\n let vsTestRes;\r\n for (let i = 0; i <= retryTimes; i++) {\r\n if (i === retryTimes) {\r\n console.error(`Failed to generate XapUt code after ${retryTimes} attempts.`);\r\n break;\r\n }\r\n\r\n const autofixPrompt = prompts;\r\n // get valid code from LLM response\r\n const llmResult = await ensureValidLLMResponse(autofixPrompt, testFramework, isXapCode, false, testFilePath, true);\r\n generatedCode = llmResult?.testCode;\r\n // write test code to test project\r\n writeTestCode(generatedCode, testFilePath);\r\n }\r\n\r\n console.log(`Autofix time: ${(Date.now() - startTime) / 1000} seconds`);\r\n\r\n return { success: true, testFilePath: testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: vsTestRes };\r\n}"]}
@@ -1,2 +1,2 @@
1
1
  import { GenResult } from '../types/genResult';
2
- export declare function generateCsharpUtCode(sourceCodePath: string, testCodePath: string, enableAutoFix: boolean, keepFailedTests: boolean, source?: string, isBenchmark?: boolean, nugetPackagePath?: string): Promise<GenResult>;
2
+ export declare function generateCsharpUtCode(sourceCodePath: string, testCodePath: string, enableAutoFix: boolean, keepFailedTests: boolean, source?: string, isBenchmark?: boolean, nugetPackagePath?: string, changedTestFiles?: string[]): Promise<GenResult>;
@@ -47,10 +47,9 @@ const getTestFile_1 = require("../utils/getTestFile");
47
47
  const installAnalyzerTool_1 = require("../analyze/installAnalyzerTool");
48
48
  const preGenProcess_1 = require("./preGen/preGenProcess");
49
49
  const preparePrompt_1 = require("../llm/preparePrompt");
50
- const removeFailedTestMethods_1 = require("../utils/removeFailedTestMethods");
51
50
  const appInsightTelemetry_1 = require("../metrics/appInsightTelemetry");
52
51
  const RETRYTIMES = 3;
53
- async function generateCsharpUtCode(sourceCodePath, testCodePath, enableAutoFix, keepFailedTests, source = constants_1.CSHARPUTGEN, isBenchmark = false, nugetPackagePath = null) {
52
+ async function generateCsharpUtCode(sourceCodePath, testCodePath, enableAutoFix, keepFailedTests, source = constants_1.CSHARPUTGEN, isBenchmark = false, nugetPackagePath = null, changedTestFiles) {
54
53
  const startTime = Date.now();
55
54
  console.log(`*****************Generating C# unit test code for: ${sourceCodePath}*****************`);
56
55
  console.log(`Current work dir: ${process.cwd()}`);
@@ -65,7 +64,7 @@ async function generateCsharpUtCode(sourceCodePath, testCodePath, enableAutoFix,
65
64
  (0, installAnalyzerTool_1.installOrUpdateAnalyzerTool)();
66
65
  let sourceCode = fs.readFileSync(sourceCodePath, 'utf-8');
67
66
  // check if source code is xap code, if so, use xap code generation prompt
68
- const isXapCode = (0, checkXapCode_1.checkXapCode)(sourceCode);
67
+ const isXapCode = (0, checkXapCode_1.checkXapCode)(sourceCodePath, sourceCode);
69
68
  sourceCode = await (0, preGenProcess_1.preGenProcess)(sourceCode, sourceCodePath, isXapCode);
70
69
  if (!sourceCode) {
71
70
  console.error(`Skip generate test for source code: ${sourceCodePath}`);
@@ -74,17 +73,20 @@ async function generateCsharpUtCode(sourceCodePath, testCodePath, enableAutoFix,
74
73
  // get code dependencies
75
74
  let codeDependency = await (0, generateCodeDependency_1.generateCodeDependency)(sourceCodePath, nugetPackagePath);
76
75
  // detect existing test file or create a new one by source code path
77
- const { testFilePath, testProjectPath, testFileExist } = (0, getTestFile_1.getOrCreatTestFile)(sourceCodePath, testCodePath, isXapCode);
76
+ const { testFilePath, testProjectPath, testFileExist } = (0, getTestFile_1.getOrCreatTestFile)(sourceCodePath, testCodePath, changedTestFiles);
78
77
  if (!testFilePath || !testProjectPath) {
79
78
  console.error(`Failed to get or create test file for source code: ${sourceCodePath}. Please check if the test project exists.`);
80
79
  return { success: false, testFilePath: undefined, testProjectPath: undefined, codeFilePath: sourceCodePath, buildResult: null, testResult: null };
81
80
  }
81
+ const originalTest = testFileExist ? fs.readFileSync(testFilePath, 'utf-8') : null;
82
82
  // get test framework
83
83
  const testFramework = (0, detectTestFramework_1.detectTestFramework)(testProjectPath);
84
84
  // prepare prompt
85
- let prompt = (0, preparePrompt_1.prepareUtGenPrompt)(sourceCodePath, sourceCode, codeDependency, isXapCode, testFramework);
85
+ let prompt = (0, preparePrompt_1.prepareUtGenPrompt)(sourceCodePath, sourceCode, codeDependency, isXapCode, testFramework, testFileExist, testFilePath);
86
86
  // call LLM service to gen code with retry
87
- const testCode = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(prompt, testFramework, isXapCode);
87
+ const llmResult = await (0, ensureValidLLMResponse_1.ensureValidLLMResponse)(prompt, testFramework, isXapCode, testFileExist, testFilePath, false, 3, sourceCode);
88
+ const testCode = llmResult?.testCode;
89
+ const insertedRanges = llmResult?.insertedRanges;
88
90
  // write test code to test project
89
91
  // To run vstest, need to write the test code to test project first, then build the test project and run the tests
90
92
  (0, fileUtils_1.writeTestCode)(testCode, testFilePath);
@@ -92,23 +94,24 @@ async function generateCsharpUtCode(sourceCodePath, testCodePath, enableAutoFix,
92
94
  let autoFixResult = { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };
93
95
  if (enableAutoFix) {
94
96
  const isVsPlugin = source === constants_1.CSVSPLUGIN;
95
- autoFixResult = await (0, autoFix_1.autoFixTestCode)(prompt, sourceCodePath, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, RETRYTIMES, isBenchmark);
97
+ autoFixResult = await (0, autoFix_1.autoFixTestCode)(prompt, sourceCodePath, sourceCode, codeDependency, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, testFileExist, keepFailedTests, insertedRanges, RETRYTIMES, isBenchmark, originalTest?.length ?? 0);
96
98
  // autoFixResult = await autoRetryTestCode(prompt, sourceCode, testCode, testProjectPath, testFilePath, isXapTest);
97
99
  }
98
100
  if (autoFixResult.success) {
99
101
  console.log(`Generate UT success time: ${(Date.now() - startTime) / 1000} seconds`);
100
102
  return autoFixResult;
101
103
  }
102
- // if retry max times or test generation failed, and keepFailedTests is false, delete failed test file or remove failed test methods
104
+ // if retry max times or test generation failed, and keepFailedTests is false, restore original state
103
105
  if (!keepFailedTests) {
104
- // keep succeed test code, or delete test file
105
- if (!autoFixResult.testResult || autoFixResult.testResult.passed === 0) {
106
- !testFileExist && (0, fileUtils_1.deleteTestFileIfExists)(testFilePath);
106
+ if (!testFileExist) {
107
+ // Original test file didn't exist, delete the failed generated file
108
+ (0, fileUtils_1.deleteTestFileIfExists)(testFilePath);
107
109
  console.log(`Failed to generate csharp test code, deleted test file: ${testFilePath}`);
108
110
  }
109
111
  else {
110
- (0, removeFailedTestMethods_1.removeFailedTestCasesInTestFile)(autoFixResult.testResult, testFilePath);
111
- console.log(`write succeed test code to file: ${testFilePath}`);
112
+ // Original test file existed, restore it
113
+ (0, fileUtils_1.writeTestCode)(originalTest, testFilePath);
114
+ console.log(`Failed to generate more tests, restored original test file: ${testFilePath}`);
112
115
  }
113
116
  }
114
117
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"csharpUtGen.js","sourceRoot":"","sources":["../../src/gen/csharpUtGen.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { CSHARPUTGEN, CSVSPLUGIN } from '../types/constants';\r\nimport { deleteTestFileIfExists, writeTestCode } from \"../utils/fileUtils\";\r\n\r\nimport { GenResult } from '../types/genResult';\r\nimport { autoFixTestCode } from './autoFix';\r\nimport { checkXapCode } from '../utils/checkXapCode';\r\nimport { detectTestFramework } from '../utils/detectTestFramework';\r\nimport { ensureValidLLMResponse } from './ensureValidLLMResponse';\r\nimport { generateCodeDependency } from '../analyze/generateCodeDependency';\r\nimport { getOrCreatTestFile } from '../utils/getTestFile';\r\nimport { installOrUpdateAnalyzerTool } from '../analyze/installAnalyzerTool';\r\nimport { preGenProcess } from './preGen/preGenProcess';\r\nimport { prepareUtGenPrompt } from '../llm/preparePrompt';\r\nimport { removeFailedTestCasesInTestFile } from '../utils/removeFailedTestMethods';\r\nimport { sendUserUsageEvent } from '../metrics/appInsightTelemetry';\r\n\r\nconst RETRYTIMES = 3;\r\n\r\nexport async function generateCsharpUtCode(\r\n sourceCodePath: string,\r\n testCodePath: string,\r\n enableAutoFix: boolean,\r\n keepFailedTests: boolean,\r\n source: string = CSHARPUTGEN,\r\n isBenchmark: boolean = false,\r\n nugetPackagePath: string = null\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n console.log(`*****************Generating C# unit test code for: ${sourceCodePath}*****************`);\r\n console.log(`Current work dir: ${process.cwd()}`);\r\n\r\n // send usage metrics\r\n sendUserUsageEvent(source);\r\n\r\n sourceCodePath = path.normalize(sourceCodePath);\r\n if (!fs.existsSync(sourceCodePath)) {\r\n console.error(`Source code file not found: ${sourceCodePath}`);\r\n return;\r\n }\r\n\r\n // install nuget cli tool to analyze code\r\n installOrUpdateAnalyzerTool();\r\n\r\n let sourceCode = fs.readFileSync(sourceCodePath, 'utf-8');\r\n\r\n // check if source code is xap code, if so, use xap code generation prompt\r\n const isXapCode = checkXapCode(sourceCode);\r\n\r\n sourceCode = await preGenProcess(sourceCode, sourceCodePath, isXapCode);\r\n if (!sourceCode) {\r\n console.error(`Skip generate test for source code: ${sourceCodePath}`);\r\n return { success: false, testFilePath: undefined, testProjectPath: undefined, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n }\r\n\r\n // get code dependencies\r\n let codeDependency = await generateCodeDependency(sourceCodePath, nugetPackagePath);\r\n\r\n // detect existing test file or create a new one by source code path\r\n const { testFilePath, testProjectPath, testFileExist } = getOrCreatTestFile(sourceCodePath, testCodePath, isXapCode);\r\n if (!testFilePath || !testProjectPath) {\r\n console.error(`Failed to get or create test file for source code: ${sourceCodePath}. Please check if the test project exists.`);\r\n return { success: false, testFilePath: undefined, testProjectPath: undefined, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n }\r\n\r\n // get test framework\r\n const testFramework = detectTestFramework(testProjectPath);\r\n\r\n // prepare prompt\r\n let prompt = prepareUtGenPrompt(sourceCodePath, sourceCode, codeDependency, isXapCode, testFramework);\r\n\r\n // call LLM service to gen code with retry\r\n const testCode = await ensureValidLLMResponse(prompt, testFramework, isXapCode);\r\n\r\n // write test code to test project\r\n // To run vstest, need to write the test code to test project first, then build the test project and run the tests\r\n writeTestCode(testCode, testFilePath);\r\n\r\n // autofix\r\n let autoFixResult: GenResult = { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n if (enableAutoFix) {\r\n const isVsPlugin = source === CSVSPLUGIN;\r\n autoFixResult = await autoFixTestCode(prompt, sourceCodePath, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, RETRYTIMES, isBenchmark);\r\n // autoFixResult = await autoRetryTestCode(prompt, sourceCode, testCode, testProjectPath, testFilePath, isXapTest);\r\n }\r\n\r\n if (autoFixResult.success) {\r\n console.log(`Generate UT success time: ${(Date.now() - startTime) / 1000} seconds`);\r\n return autoFixResult;\r\n }\r\n\r\n // if retry max times or test generation failed, and keepFailedTests is false, delete failed test file or remove failed test methods\r\n if (!keepFailedTests) {\r\n // keep succeed test code, or delete test file\r\n if (!autoFixResult.testResult || autoFixResult.testResult.passed === 0) {\r\n !testFileExist && deleteTestFileIfExists(testFilePath);\r\n console.log(`Failed to generate csharp test code, deleted test file: ${testFilePath}`);\r\n } else {\r\n removeFailedTestCasesInTestFile(autoFixResult.testResult, testFilePath);\r\n console.log(`write succeed test code to file: ${testFilePath}`);\r\n }\r\n } else {\r\n console.log(`keep failed test file: ${testFilePath}`);\r\n }\r\n console.log(`Generate UT failed time: ${(Date.now() - startTime) / 1000} seconds`);\r\n return autoFixResult;\r\n}\r\n\r\n// generateCsharpUtCode(\"D:\\\\code\\\\IndexServe\\\\private\\\\indexserve\\\\RecommendationEngine\\\\RecoPS\\\\PSTableClient\\\\PSTableClient.cs\", undefined, false, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Overview\\\\HttpRequestParser\\\\Utils\\\\SqmidHelper.cs\", undefined, true, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Eplant\\\\ResponseBuilders\\\\EplantMigrateResponseBuilder.cs\", undefined, true, true, true);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UCMDynamics.AppointmentPlugin\\\\AppointmentOperation.cs\", undefined, false, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\AIUnitTestExample\\\\src\\\\ToListinator.Analyzers\\\\ToListCountAnalyzer.cs\", undefined, true, true, false);\r\n"]}
1
+ {"version":3,"file":"csharpUtGen.js","sourceRoot":"","sources":["../../src/gen/csharpUtGen.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { CSHARPUTGEN, CSVSPLUGIN } from '../types/constants';\r\nimport { deleteTestFileIfExists, writeTestCode } from \"../utils/fileUtils\";\r\n\r\nimport { GenResult } from '../types/genResult';\r\nimport { autoFixTestCode } from './autoFix';\r\nimport { checkXapCode } from '../utils/checkXapCode';\r\nimport { detectTestFramework } from '../utils/detectTestFramework';\r\nimport { ensureValidLLMResponse } from './ensureValidLLMResponse';\r\nimport { generateCodeDependency } from '../analyze/generateCodeDependency';\r\nimport { getOrCreatTestFile } from '../utils/getTestFile';\r\nimport { installOrUpdateAnalyzerTool } from '../analyze/installAnalyzerTool';\r\nimport { preGenProcess } from './preGen/preGenProcess';\r\nimport { prepareUtGenPrompt } from '../llm/preparePrompt';\r\nimport { sendUserUsageEvent } from '../metrics/appInsightTelemetry';\r\n\r\nconst RETRYTIMES = 3;\r\n\r\nexport async function generateCsharpUtCode(\r\n sourceCodePath: string,\r\n testCodePath: string,\r\n enableAutoFix: boolean,\r\n keepFailedTests: boolean,\r\n source: string = CSHARPUTGEN,\r\n isBenchmark: boolean = false,\r\n nugetPackagePath: string = null,\r\n changedTestFiles?: string[]\r\n): Promise<GenResult> {\r\n const startTime = Date.now();\r\n\r\n console.log(`*****************Generating C# unit test code for: ${sourceCodePath}*****************`);\r\n console.log(`Current work dir: ${process.cwd()}`);\r\n\r\n // send usage metrics\r\n sendUserUsageEvent(source);\r\n\r\n sourceCodePath = path.normalize(sourceCodePath);\r\n if (!fs.existsSync(sourceCodePath)) {\r\n console.error(`Source code file not found: ${sourceCodePath}`);\r\n return;\r\n }\r\n\r\n // install nuget cli tool to analyze code\r\n installOrUpdateAnalyzerTool();\r\n\r\n let sourceCode = fs.readFileSync(sourceCodePath, 'utf-8');\r\n\r\n // check if source code is xap code, if so, use xap code generation prompt\r\n const isXapCode = checkXapCode(sourceCodePath, sourceCode);\r\n\r\n sourceCode = await preGenProcess(sourceCode, sourceCodePath, isXapCode);\r\n if (!sourceCode) {\r\n console.error(`Skip generate test for source code: ${sourceCodePath}`);\r\n return { success: false, testFilePath: undefined, testProjectPath: undefined, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n }\r\n\r\n // get code dependencies\r\n let codeDependency = await generateCodeDependency(sourceCodePath, nugetPackagePath);\r\n\r\n // detect existing test file or create a new one by source code path\r\n const { testFilePath, testProjectPath, testFileExist } = getOrCreatTestFile(sourceCodePath, testCodePath, changedTestFiles);\r\n if (!testFilePath || !testProjectPath) {\r\n console.error(`Failed to get or create test file for source code: ${sourceCodePath}. Please check if the test project exists.`);\r\n return { success: false, testFilePath: undefined, testProjectPath: undefined, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n }\r\n\r\n const originalTest = testFileExist ? fs.readFileSync(testFilePath, 'utf-8') : null;\r\n\r\n // get test framework\r\n const testFramework = detectTestFramework(testProjectPath);\r\n\r\n // prepare prompt\r\n let prompt = prepareUtGenPrompt(sourceCodePath, sourceCode, codeDependency, isXapCode, testFramework, testFileExist, testFilePath);\r\n\r\n // call LLM service to gen code with retry\r\n const llmResult = await ensureValidLLMResponse(prompt, testFramework, isXapCode, testFileExist, testFilePath, false, 3, sourceCode);\r\n const testCode = llmResult?.testCode;\r\n const insertedRanges = llmResult?.insertedRanges;\r\n\r\n // write test code to test project\r\n // To run vstest, need to write the test code to test project first, then build the test project and run the tests\r\n writeTestCode(testCode, testFilePath);\r\n\r\n // autofix\r\n let autoFixResult: GenResult = { success: true, testFilePath, testProjectPath, codeFilePath: sourceCodePath, buildResult: null, testResult: null };\r\n if (enableAutoFix) {\r\n const isVsPlugin = source === CSVSPLUGIN;\r\n autoFixResult = await autoFixTestCode(prompt, sourceCodePath, sourceCode, codeDependency, testCode, testProjectPath, testFilePath, testFramework, isXapCode, isVsPlugin, testFileExist, keepFailedTests, insertedRanges, RETRYTIMES, isBenchmark, originalTest?.length ?? 0);\r\n // autoFixResult = await autoRetryTestCode(prompt, sourceCode, testCode, testProjectPath, testFilePath, isXapTest);\r\n }\r\n\r\n if (autoFixResult.success) {\r\n console.log(`Generate UT success time: ${(Date.now() - startTime) / 1000} seconds`);\r\n return autoFixResult;\r\n }\r\n\r\n // if retry max times or test generation failed, and keepFailedTests is false, restore original state\r\n if (!keepFailedTests) {\r\n if (!testFileExist) {\r\n // Original test file didn't exist, delete the failed generated file\r\n deleteTestFileIfExists(testFilePath);\r\n console.log(`Failed to generate csharp test code, deleted test file: ${testFilePath}`);\r\n } else {\r\n // Original test file existed, restore it\r\n writeTestCode(originalTest, testFilePath);\r\n console.log(`Failed to generate more tests, restored original test file: ${testFilePath}`);\r\n }\r\n } else {\r\n console.log(`keep failed test file: ${testFilePath}`);\r\n }\r\n console.log(`Generate UT failed time: ${(Date.now() - startTime) / 1000} seconds`);\r\n return autoFixResult;\r\n}\r\n\r\n// generateCsharpUtCode(\"D:\\\\code\\\\IndexServe\\\\private\\\\indexserve\\\\RecommendationEngine\\\\RecoPS\\\\PSTableClient\\\\PSTableClient.cs\", undefined, false, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Overview\\\\HttpRequestParser\\\\Utils\\\\SqmidHelper.cs\", undefined, true, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Eplant\\\\ResponseBuilders\\\\EplantMigrateResponseBuilder.cs\", undefined, true, true, true);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UCMDynamics.AppointmentPlugin\\\\AppointmentOperation.cs\", undefined, false, true, false);\r\n// generateCsharpUtCode(\"D:\\\\code\\\\AIUnitTestExample\\\\src\\\\ToListinator.Analyzers\\\\ToListCountAnalyzer.cs\", undefined, true, true, false);\r\n"]}
@@ -1 +1,5 @@
1
- export declare function ensureValidLLMResponse(prompt: any[], testFramework: string, isXapCode: boolean, retryTimes?: number): Promise<string>;
1
+ export interface LLMResponseResult {
2
+ testCode: string;
3
+ insertedRanges?: [number, number][];
4
+ }
5
+ export declare function ensureValidLLMResponse(prompt: any[], testFramework: string, isXapCode: boolean, testFileExist: boolean, testFilePath: string, isAutoFix?: boolean, retryTimes?: number, sourceCode?: string): Promise<LLMResponseResult>;