@ai-dev-tools/csharp-copilot-core 0.0.40 → 0.0.41

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.
@@ -58,7 +58,7 @@ function processSourceFile(sourceFile, changedTestFiles) {
58
58
  console.warn(`Failed to get test file for ${sourceFile.filepath}: ${error}`);
59
59
  }
60
60
  // Find runsettings file from test project path
61
- const runsettingsFilePath = testFilePath ? (0, getCodeCoverageSetting_1.getCodeCoverageSetting)(testFilePath) : null;
61
+ const runsettingsFilePath = (0, getCodeCoverageSetting_1.getCodeCoverageSetting)(fullSourcePath);
62
62
  return {
63
63
  sourceFile,
64
64
  testFilePath,
@@ -1 +1 @@
1
- {"version":3,"file":"processChangedFiles.js","sourceRoot":"","sources":["../../src/changedFilesProcessor/processChangedFiles.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { getOrCreatTestFile, isTestFile } from '../utils/getTestFile';\r\nimport { getCodeRepoRoot, findSolutionFile } from '../utils/getCodeStructurePath';\r\nimport { getCodeCoverageSetting } from '../codeCoverage/getCodeCoverageSetting';\r\nimport { ChangedFileEntry, CategorizedFiles, ProcessedSourceFile, ChangedFileResult, ProcessChangedFilesResult } from '../types/changedFilesResult';\r\n\r\nexport type { CategorizedFiles, ProcessedSourceFile, ChangedFileResult, ProcessChangedFilesResult };\r\n\r\n/**\r\n * Process a single source file to get all related paths.\r\n * @param sourceFile - The changed file entry (filepath should be absolute path from CI)\r\n * @param changedTestFiles - List of changed test file paths from the config\r\n */\r\nfunction processSourceFile(sourceFile: ChangedFileEntry, changedTestFiles: string[]): ProcessedSourceFile {\r\n const fullSourcePath = path.normalize(sourceFile.filepath);\r\n\r\n // Find solution file\r\n const solutionFilePath = findSolutionFile(fullSourcePath);\r\n\r\n // Get test file path\r\n let testFilePath: string | null = null;\r\n try {\r\n const result = getOrCreatTestFile(fullSourcePath, undefined, changedTestFiles);\r\n testFilePath = result.testFilePath;\r\n } catch (error) {\r\n console.warn(`Failed to get test file for ${sourceFile.filepath}: ${error}`);\r\n }\r\n\r\n // Find runsettings file from test project path\r\n const runsettingsFilePath = testFilePath ? getCodeCoverageSetting(testFilePath) : null;\r\n\r\n return {\r\n sourceFile,\r\n testFilePath,\r\n runsettingsFilePath,\r\n solutionFilePath\r\n };\r\n}\r\n\r\n/**\r\n * Read and parse the changed files config, filter CS files, and categorize them.\r\n */\r\nfunction readAndCategorizeChangedFiles(configPath: string): CategorizedFiles {\r\n const configContent = fs.readFileSync(configPath, 'utf-8');\r\n const parsed: unknown = JSON.parse(configContent);\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new Error(`Changed files config is not an array: ${configPath}`);\r\n }\r\n\r\n const allFiles: ChangedFileEntry[] = parsed.filter(\r\n (entry): entry is ChangedFileEntry =>\r\n entry != null &&\r\n typeof entry === 'object' &&\r\n typeof (entry as any).filepath === 'string'\r\n );\r\n\r\n // Filter only .cs files\r\n const csFiles = allFiles.filter(entry => entry.filepath.toLowerCase().endsWith('.cs'));\r\n\r\n // Categorize into test files and source files\r\n const testFiles: ChangedFileEntry[] = [];\r\n const sourceFiles: ChangedFileEntry[] = [];\r\n\r\n for (const file of csFiles) {\r\n if (isTestFile(file.filepath)) {\r\n testFiles.push(file);\r\n } else {\r\n sourceFiles.push(file);\r\n }\r\n }\r\n\r\n console.log(`Found ${csFiles.length} CS files: ${testFiles.length} test files, ${sourceFiles.length} source files`);\r\n\r\n return { testFiles, sourceFiles };\r\n}\r\n\r\n/**\r\n * Process changed files from a config file path.\r\n * @param changedFilesConfigPath - Path to the JSON config file containing changed files array\r\n * @param options - Additional command line options\r\n * @returns Result with most common solution, its runsettings, and changed files with test paths\r\n */\r\nexport async function processChangedFiles(changedFilesConfigPath: string, options: Record<string, unknown>): Promise<ProcessChangedFilesResult> {\r\n console.log(`Processing changed files from config: ${changedFilesConfigPath}`);\r\n\r\n // Read and categorize files\r\n const { testFiles, sourceFiles } = readAndCategorizeChangedFiles(changedFilesConfigPath);\r\n\r\n console.log('Test files:', testFiles.map(f => f.filepath));\r\n console.log('Source files:', sourceFiles.map(f => f.filepath));\r\n\r\n // Process each source file\r\n const changedTestFilePaths = testFiles.map(f => f.filepath);\r\n const processedFiles: ProcessedSourceFile[] = [];\r\n for (const sourceFile of sourceFiles) {\r\n const processed = processSourceFile(sourceFile, changedTestFilePaths);\r\n processedFiles.push(processed);\r\n console.log(`Processed: ${sourceFile.filepath}`);\r\n console.log(` Solution: ${processed.solutionFilePath || 'not found'}`);\r\n console.log(` Runsettings: ${processed.runsettingsFilePath || 'not found'}`);\r\n console.log(` Test file: ${processed.testFilePath || 'not found'}`);\r\n }\r\n\r\n // solutionPath -> {file count, runsettings}\r\n const solutionCounts = new Map<string, { count: number; runsettingsFilePath: string | null }>();\r\n for (const file of processedFiles) {\r\n if (file.solutionFilePath) {\r\n const existing = solutionCounts.get(file.solutionFilePath);\r\n if (existing) {\r\n existing.count++;\r\n } else {\r\n solutionCounts.set(file.solutionFilePath, { \r\n count: 1, \r\n runsettingsFilePath: file.runsettingsFilePath \r\n });\r\n }\r\n }\r\n }\r\n\r\n // Get the solution with the highest count\r\n let mostCommonSolution: string | null = null;\r\n let mostCommonRunsettings: string | null = null;\r\n if (solutionCounts.size > 0) {\r\n const [solution, data] = [...solutionCounts.entries()]\r\n .reduce((a, b) => a[1].count > b[1].count ? a : b);\r\n mostCommonSolution = solution;\r\n mostCommonRunsettings = data.runsettingsFilePath;\r\n }\r\n\r\n // Build the changed file array\r\n const changedFiles: ChangedFileResult[] = processedFiles.map(file => ({\r\n filepath: file.sourceFile.filepath,\r\n testfilepath: file.testFilePath\r\n }));\r\n\r\n const result: ProcessChangedFilesResult = {\r\n solutionFilePath: mostCommonSolution,\r\n runsettingsFilePath: mostCommonRunsettings,\r\n changedFiles\r\n };\r\n\r\n console.log(`Result: Solution=${mostCommonSolution}, Runsettings=${mostCommonRunsettings}, ChangedFiles=${changedFiles.length}`);\r\n\r\n return result;\r\n}\r\n"]}
1
+ {"version":3,"file":"processChangedFiles.js","sourceRoot":"","sources":["../../src/changedFilesProcessor/processChangedFiles.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { getOrCreatTestFile, isTestFile } from '../utils/getTestFile';\r\nimport { getCodeRepoRoot, findSolutionFile } from '../utils/getCodeStructurePath';\r\nimport { getCodeCoverageSetting } from '../codeCoverage/getCodeCoverageSetting';\r\nimport { ChangedFileEntry, CategorizedFiles, ProcessedSourceFile, ChangedFileResult, ProcessChangedFilesResult } from '../types/changedFilesResult';\r\n\r\nexport type { CategorizedFiles, ProcessedSourceFile, ChangedFileResult, ProcessChangedFilesResult };\r\n\r\n/**\r\n * Process a single source file to get all related paths.\r\n * @param sourceFile - The changed file entry (filepath should be absolute path from CI)\r\n * @param changedTestFiles - List of changed test file paths from the config\r\n */\r\nfunction processSourceFile(sourceFile: ChangedFileEntry, changedTestFiles: string[]): ProcessedSourceFile {\r\n const fullSourcePath = path.normalize(sourceFile.filepath);\r\n\r\n // Find solution file\r\n const solutionFilePath = findSolutionFile(fullSourcePath);\r\n\r\n // Get test file path\r\n let testFilePath: string | null = null;\r\n try {\r\n const result = getOrCreatTestFile(fullSourcePath, undefined, changedTestFiles);\r\n testFilePath = result.testFilePath;\r\n } catch (error) {\r\n console.warn(`Failed to get test file for ${sourceFile.filepath}: ${error}`);\r\n }\r\n\r\n // Find runsettings file from test project path\r\n const runsettingsFilePath = getCodeCoverageSetting(fullSourcePath);\r\n\r\n return {\r\n sourceFile,\r\n testFilePath,\r\n runsettingsFilePath,\r\n solutionFilePath\r\n };\r\n}\r\n\r\n/**\r\n * Read and parse the changed files config, filter CS files, and categorize them.\r\n */\r\nfunction readAndCategorizeChangedFiles(configPath: string): CategorizedFiles {\r\n const configContent = fs.readFileSync(configPath, 'utf-8');\r\n const parsed: unknown = JSON.parse(configContent);\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new Error(`Changed files config is not an array: ${configPath}`);\r\n }\r\n\r\n const allFiles: ChangedFileEntry[] = parsed.filter(\r\n (entry): entry is ChangedFileEntry =>\r\n entry != null &&\r\n typeof entry === 'object' &&\r\n typeof (entry as any).filepath === 'string'\r\n );\r\n\r\n // Filter only .cs files\r\n const csFiles = allFiles.filter(entry => entry.filepath.toLowerCase().endsWith('.cs'));\r\n\r\n // Categorize into test files and source files\r\n const testFiles: ChangedFileEntry[] = [];\r\n const sourceFiles: ChangedFileEntry[] = [];\r\n\r\n for (const file of csFiles) {\r\n if (isTestFile(file.filepath)) {\r\n testFiles.push(file);\r\n } else {\r\n sourceFiles.push(file);\r\n }\r\n }\r\n\r\n console.log(`Found ${csFiles.length} CS files: ${testFiles.length} test files, ${sourceFiles.length} source files`);\r\n\r\n return { testFiles, sourceFiles };\r\n}\r\n\r\n/**\r\n * Process changed files from a config file path.\r\n * @param changedFilesConfigPath - Path to the JSON config file containing changed files array\r\n * @param options - Additional command line options\r\n * @returns Result with most common solution, its runsettings, and changed files with test paths\r\n */\r\nexport async function processChangedFiles(changedFilesConfigPath: string, options: Record<string, unknown>): Promise<ProcessChangedFilesResult> {\r\n console.log(`Processing changed files from config: ${changedFilesConfigPath}`);\r\n\r\n // Read and categorize files\r\n const { testFiles, sourceFiles } = readAndCategorizeChangedFiles(changedFilesConfigPath);\r\n\r\n console.log('Test files:', testFiles.map(f => f.filepath));\r\n console.log('Source files:', sourceFiles.map(f => f.filepath));\r\n\r\n // Process each source file\r\n const changedTestFilePaths = testFiles.map(f => f.filepath);\r\n const processedFiles: ProcessedSourceFile[] = [];\r\n for (const sourceFile of sourceFiles) {\r\n const processed = processSourceFile(sourceFile, changedTestFilePaths);\r\n processedFiles.push(processed);\r\n console.log(`Processed: ${sourceFile.filepath}`);\r\n console.log(` Solution: ${processed.solutionFilePath || 'not found'}`);\r\n console.log(` Runsettings: ${processed.runsettingsFilePath || 'not found'}`);\r\n console.log(` Test file: ${processed.testFilePath || 'not found'}`);\r\n }\r\n\r\n // solutionPath -> {file count, runsettings}\r\n const solutionCounts = new Map<string, { count: number; runsettingsFilePath: string | null }>();\r\n for (const file of processedFiles) {\r\n if (file.solutionFilePath) {\r\n const existing = solutionCounts.get(file.solutionFilePath);\r\n if (existing) {\r\n existing.count++;\r\n } else {\r\n solutionCounts.set(file.solutionFilePath, { \r\n count: 1, \r\n runsettingsFilePath: file.runsettingsFilePath \r\n });\r\n }\r\n }\r\n }\r\n\r\n // Get the solution with the highest count\r\n let mostCommonSolution: string | null = null;\r\n let mostCommonRunsettings: string | null = null;\r\n if (solutionCounts.size > 0) {\r\n const [solution, data] = [...solutionCounts.entries()]\r\n .reduce((a, b) => a[1].count > b[1].count ? a : b);\r\n mostCommonSolution = solution;\r\n mostCommonRunsettings = data.runsettingsFilePath;\r\n }\r\n\r\n // Build the changed file array\r\n const changedFiles: ChangedFileResult[] = processedFiles.map(file => ({\r\n filepath: file.sourceFile.filepath,\r\n testfilepath: file.testFilePath\r\n }));\r\n\r\n const result: ProcessChangedFilesResult = {\r\n solutionFilePath: mostCommonSolution,\r\n runsettingsFilePath: mostCommonRunsettings,\r\n changedFiles\r\n };\r\n\r\n console.log(`Result: Solution=${mostCommonSolution}, Runsettings=${mostCommonRunsettings}, ChangedFiles=${changedFiles.length}`);\r\n\r\n return result;\r\n}\r\n"]}
@@ -23,7 +23,7 @@ async function ensureValidLLMResponse(prompt, testFramework, isXapCode, isMoreUT
23
23
  testCode = (0, postGenMoreUTAutofixProcess_1.postGenMoreUTAutofixProcess)(generatedCode, testFramework, isXapCode, sourceCode, testFilePath, errorMethodNames);
24
24
  }
25
25
  else {
26
- testCode = (0, postGenProcess_1.postGenProcess)(generatedCode, testFramework, isXapCode, sourceCode);
26
+ testCode = (0, postGenProcess_1.postGenProcess)(generatedCode, testFramework, isXapCode, sourceCode, testFilePath);
27
27
  }
28
28
  if (!!testCode) {
29
29
  return { testCode, insertedRanges };
@@ -1 +1 @@
1
- {"version":3,"file":"ensureValidLLMResponse.js","sourceRoot":"","sources":["../../src/gen/ensureValidLLMResponse.ts"],"names":[],"mappings":";;AAUA,wDA0BC;AApCD,6DAA0D;AAC1D,yEAAsE;AACtE,uFAAoF;AACpF,8DAA2D;AAOpD,KAAK,UAAU,sBAAsB,CAAC,MAAa,EAAE,aAAqB,EAAE,SAAkB,EAAE,gBAAyB,EAAE,YAAoB,EAAE,YAAqB,KAAK,EAAE,aAAqB,CAAC,EAAE,UAAmB,EAAE,gBAA2B;IACxP,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,+BAA+B;QAC/B,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,IAAA,mCAAgB,EAAC,MAAM,CAAC,CAAC;QAElE,uCAAuC;QACvC,IAAI,QAAgB,CAAC;QACrB,IAAI,cAAc,GAAuB,SAAS,CAAC;QACnD,IAAI,gBAAgB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,aAAa,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YAC5E,IAAI,MAAM,EAAE,CAAC;gBACT,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAC3B,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;YAC3C,CAAC;QACL,CAAC;aAAM,IAAI,gBAAgB,IAAI,SAAS,EAAE,CAAC;YACvC,QAAQ,GAAG,IAAA,yDAA2B,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAChI,CAAC;aAAM,CAAC;YACJ,QAAQ,GAAG,IAAA,+BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["import { postGenProcess } from \"./postGen/postGenProcess\";\r\nimport { postGenMoreUTProcess } from \"./postGen/postGenMoreUTProcess\";\r\nimport { postGenMoreUTAutofixProcess } from \"./postGen/postGenMoreUTAutofixProcess\";\r\nimport { sendRequestToLLM } from \"../llm/sendRequestToLLM\";\r\n\r\nexport interface LLMResponseResult {\r\n testCode: string;\r\n insertedRanges?: [number, number][];\r\n}\r\n\r\nexport async function ensureValidLLMResponse(prompt: any[], testFramework: string, isXapCode: boolean, isMoreUTScenario: boolean, testFilePath: string, isAutoFix: boolean = false, retryTimes: number = 3, sourceCode?: string, errorMethodNames?: string[]): Promise<LLMResponseResult> {\r\n for (let i = 0; i < retryTimes; i++) {\r\n // call LLM service to gen code\r\n const { content: generatedCode } = await sendRequestToLLM(prompt);\r\n \r\n // extract valid code from LLM response\r\n let testCode: string;\r\n let insertedRanges: [number, number][] = undefined;\r\n if (isMoreUTScenario && !isAutoFix) {\r\n const result = postGenMoreUTProcess(generatedCode, testFilePath, isXapCode);\r\n if (result) {\r\n testCode = result.testCode;\r\n insertedRanges = result.insertedRanges;\r\n }\r\n } else if (isMoreUTScenario && isAutoFix) {\r\n testCode = postGenMoreUTAutofixProcess(generatedCode, testFramework, isXapCode, sourceCode, testFilePath, errorMethodNames);\r\n } else {\r\n testCode = postGenProcess(generatedCode, testFramework, isXapCode, sourceCode);\r\n }\r\n if (!!testCode) {\r\n return { testCode, insertedRanges };\r\n }\r\n console.log(`Failed to generate valid test code, retrying... (${i + 1}/${retryTimes})`);\r\n }\r\n\r\n return undefined;\r\n}"]}
1
+ {"version":3,"file":"ensureValidLLMResponse.js","sourceRoot":"","sources":["../../src/gen/ensureValidLLMResponse.ts"],"names":[],"mappings":";;AAUA,wDA0BC;AApCD,6DAA0D;AAC1D,yEAAsE;AACtE,uFAAoF;AACpF,8DAA2D;AAOpD,KAAK,UAAU,sBAAsB,CAAC,MAAa,EAAE,aAAqB,EAAE,SAAkB,EAAE,gBAAyB,EAAE,YAAoB,EAAE,YAAqB,KAAK,EAAE,aAAqB,CAAC,EAAE,UAAmB,EAAE,gBAA2B;IACxP,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,+BAA+B;QAC/B,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,IAAA,mCAAgB,EAAC,MAAM,CAAC,CAAC;QAElE,uCAAuC;QACvC,IAAI,QAAgB,CAAC;QACrB,IAAI,cAAc,GAAuB,SAAS,CAAC;QACnD,IAAI,gBAAgB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,aAAa,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YAC5E,IAAI,MAAM,EAAE,CAAC;gBACT,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAC3B,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;YAC3C,CAAC;QACL,CAAC;aAAM,IAAI,gBAAgB,IAAI,SAAS,EAAE,CAAC;YACvC,QAAQ,GAAG,IAAA,yDAA2B,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;QAChI,CAAC;aAAM,CAAC;YACJ,QAAQ,GAAG,IAAA,+BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;QACjG,CAAC;QACD,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["import { postGenProcess } from \"./postGen/postGenProcess\";\r\nimport { postGenMoreUTProcess } from \"./postGen/postGenMoreUTProcess\";\r\nimport { postGenMoreUTAutofixProcess } from \"./postGen/postGenMoreUTAutofixProcess\";\r\nimport { sendRequestToLLM } from \"../llm/sendRequestToLLM\";\r\n\r\nexport interface LLMResponseResult {\r\n testCode: string;\r\n insertedRanges?: [number, number][];\r\n}\r\n\r\nexport async function ensureValidLLMResponse(prompt: any[], testFramework: string, isXapCode: boolean, isMoreUTScenario: boolean, testFilePath: string, isAutoFix: boolean = false, retryTimes: number = 3, sourceCode?: string, errorMethodNames?: string[]): Promise<LLMResponseResult> {\r\n for (let i = 0; i < retryTimes; i++) {\r\n // call LLM service to gen code\r\n const { content: generatedCode } = await sendRequestToLLM(prompt);\r\n \r\n // extract valid code from LLM response\r\n let testCode: string;\r\n let insertedRanges: [number, number][] = undefined;\r\n if (isMoreUTScenario && !isAutoFix) {\r\n const result = postGenMoreUTProcess(generatedCode, testFilePath, isXapCode);\r\n if (result) {\r\n testCode = result.testCode;\r\n insertedRanges = result.insertedRanges;\r\n }\r\n } else if (isMoreUTScenario && isAutoFix) {\r\n testCode = postGenMoreUTAutofixProcess(generatedCode, testFramework, isXapCode, sourceCode, testFilePath, errorMethodNames);\r\n } else {\r\n testCode = postGenProcess(generatedCode, testFramework, isXapCode, sourceCode, testFilePath);\r\n }\r\n if (!!testCode) {\r\n return { testCode, insertedRanges };\r\n }\r\n console.log(`Failed to generate valid test code, retrying... (${i + 1}/${retryTimes})`);\r\n }\r\n\r\n return undefined;\r\n}"]}
@@ -45,6 +45,7 @@ const fs = __importStar(require("fs"));
45
45
  const repairRequiredNameSpaces_1 = require("./repairRequiredNameSpaces");
46
46
  const constants_1 = require("../../types/constants");
47
47
  const removeFailedTestMethods_1 = require("../../utils/removeFailedTestMethods");
48
+ const writeGenCode_1 = require("../../utils/writeGenCode");
48
49
  /**
49
50
  * Post-process LLM-generated content for the "more UT" scenario.
50
51
  *
@@ -69,6 +70,7 @@ function postGenMoreUTProcess(generatedContent, testFilePath, isXapCode) {
69
70
  if (!parsed) {
70
71
  return undefined;
71
72
  }
73
+ (0, writeGenCode_1.writeAIRawCode)(generatedContent, testFilePath);
72
74
  const { usingStatements, testMethods, helperCode } = parsed;
73
75
  // Step 2: Read and normalise the original test file
74
76
  const originalTestCode = fs.readFileSync(testFilePath, 'utf-8');
@@ -1 +1 @@
1
- {"version":3,"file":"postGenMoreUTProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenMoreUTProcess.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\n\r\nimport { detectUsingInsertPosition, repairXapRequiredNameSpaces, XAP_REQUIRED_USINGS } from \"./repairRequiredNameSpaces\";\r\nimport { XapBondRelatedNamespace } from \"../../types/constants\";\r\nimport { extractMethodName, findTestMethodRangeByBrace } from '../../utils/removeFailedTestMethods';\r\n\r\n/** Result of the post-generation process for additional unit tests */\r\ninterface MoreUTResult {\r\n testCode: string;\r\n insertedRanges: [number, number][];\r\n}\r\n\r\n/** Parsed sections from the LLM-generated content */\r\ninterface ParsedMoreUtContent {\r\n usingStatements: string;\r\n testMethods: string;\r\n helperCode: string;\r\n}\r\n\r\n/**\r\n * Post-process LLM-generated content for the \"more UT\" scenario.\r\n *\r\n * Unlike `postGenProcess` which handles brand-new test files, this function\r\n * merges newly generated test methods, using statements and helper code into\r\n * an **existing** test file. It:\r\n * 1. Parses the structured LLM response (USING_STATEMENTS / TEST_METHODS / HELPER_CODE sections).\r\n * 2. De-duplicates and inserts new `using` directives at the correct position.\r\n * 3. Inserts new test methods right after the last existing test method.\r\n * 4. Appends helper code immediately after the newly inserted test methods.\r\n * 5. Preserves the original line-ending style (CRLF / LF).\r\n *\r\n * @param generatedContent Raw LLM response containing fenced code sections.\r\n * @param testFilePath Absolute path to the existing test file on disk.\r\n * @param isXapCode Whether Xap-specific using directives should be injected.\r\n * @returns An object with the merged test code and the line ranges that were inserted,\r\n * or `undefined` if the generated content could not be parsed.\r\n */\r\nexport function postGenMoreUTProcess(\r\n generatedContent: string,\r\n testFilePath: string,\r\n isXapCode: boolean\r\n): MoreUTResult | undefined {\r\n // Step 1: Parse the structured LLM response\r\n const parsed = parseGeneratedMoreUtContent(generatedContent);\r\n if (!parsed) {\r\n return undefined;\r\n }\r\n\r\n const { usingStatements, testMethods, helperCode } = parsed;\r\n\r\n // Step 2: Read and normalise the original test file\r\n const originalTestCode = fs.readFileSync(testFilePath, 'utf-8');\r\n const lineEnding = detectLineEnding(originalTestCode);\r\n const normalizedOriginal = originalTestCode.replace(/\\r\\n/g, '\\n');\r\n const originalLines = normalizedOriginal.split('\\n');\r\n\r\n // Step 3: Detect the indentation convention used in the file\r\n const baseIndent = detectTestMethodIndent(originalLines);\r\n\r\n const insertedRanges: [number, number][] = [];\r\n let resultLines = [...originalLines];\r\n let offset = 0;\r\n\r\n // Step 4: Insert using statements (if any)\r\n const usingResult = insertUsingStatements(\r\n resultLines, usingStatements, isXapCode, testMethods, helperCode, offset\r\n );\r\n resultLines = usingResult.lines;\r\n if (usingResult.range) {\r\n insertedRanges.push(usingResult.range);\r\n }\r\n offset += usingResult.linesInserted;\r\n\r\n // Step 5: Insert new test methods\r\n let testMethodInsertEnd = 0;\r\n const testMethodResult = insertTestMethods(resultLines, testMethods, baseIndent, originalLines, offset);\r\n resultLines = testMethodResult.lines;\r\n if (testMethodResult.range) {\r\n insertedRanges.push(testMethodResult.range);\r\n testMethodInsertEnd = testMethodResult.insertEnd;\r\n }\r\n offset += testMethodResult.linesInserted;\r\n\r\n // Step 6: Insert helper code right after the test methods\r\n const helperResult = insertHelperCode(\r\n resultLines, helperCode, baseIndent, originalLines, offset, testMethodInsertEnd\r\n );\r\n resultLines = helperResult.lines;\r\n if (helperResult.range) {\r\n insertedRanges.push(helperResult.range);\r\n }\r\n\r\n // Step 7: Restore the original line-ending style\r\n let testCode = resultLines.join('\\n').replace(/\\n/g, lineEnding);\r\n \r\n // Step 8: Remove trailing whitespace from each line (trim_trailing_whitespace)\r\n testCode = testCode.split(lineEnding).map(line => line.replace(/\\s+$/, '')).join(lineEnding);\r\n \r\n console.log(`Post generation (more UT) process completed, code length: ${testCode.length}`);\r\n\r\n return { testCode, insertedRanges };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Section inserters – each returns the mutated line array, the inserted range\r\n// and the number of lines added so callers can maintain an offset.\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Insert new `using` directives that don't already exist in the file.\r\n * Also injects Xap-specific usings when `isXapCode` is true.\r\n */\r\nfunction insertUsingStatements(\r\n resultLines: string[],\r\n usingStatements: string | undefined,\r\n isXapCode: boolean,\r\n testMethods: string | undefined,\r\n helperCode: string | undefined,\r\n offset: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number } {\r\n if (!usingStatements?.trim() && !isXapCode) {\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n // Collect all using statements (user-provided + Xap-specific)\r\n let allUsingStatements = usingStatements ? usingStatements.replace(/\\r\\n/g, '\\n') : '';\r\n\r\n if (isXapCode) {\r\n const xapUsings = [...XAP_REQUIRED_USINGS];\r\n // Only add XapBondRelatedNamespace if generated code references XapBlob\r\n if ((testMethods && testMethods.includes('XapBlob')) || (helperCode && helperCode.includes('XapBlob'))) {\r\n xapUsings.push(XapBondRelatedNamespace);\r\n }\r\n const xapUsingsStr = xapUsings.join('\\n');\r\n allUsingStatements = allUsingStatements ? `${allUsingStatements}\\n${xapUsingsStr}` : xapUsingsStr;\r\n }\r\n\r\n // De-duplicate against the original file AND within the merged list itself\r\n const existingUsings = extractExistingUsingStatements(resultLines);\r\n const newUsingLines = allUsingStatements\r\n .split('\\n')\r\n .filter(line => line.trim() !== '')\r\n .filter(line => {\r\n const normalized = normalizeUsingStatement(line);\r\n if (!normalized || existingUsings.has(normalized)) return false;\r\n return existingUsings.add(normalized); // Set.add() returns the Set (truthy)\r\n });\r\n\r\n if (newUsingLines.length === 0) {\r\n console.log('All using statements already exist in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n // Determine where and with what indentation to insert\r\n const { insertIndex: insertUsingAt, indent: usingIndent } = detectUsingInsertPosition(resultLines);\r\n const indentedUsing = applyIndentation(newUsingLines.join('\\n'), usingIndent);\r\n const usingLines = indentedUsing.split('\\n').filter(line => line.trim() !== '');\r\n\r\n const insertIndex = insertUsingAt + offset;\r\n resultLines.splice(insertIndex, 0, ...usingLines);\r\n\r\n const usingStartLine = insertIndex + 1;\r\n const usingEndLine = insertIndex + usingLines.length;\r\n console.log(`Inserted ${usingLines.length} using lines at index ${insertIndex}, range: [${usingStartLine}, ${usingEndLine}]`);\r\n\r\n return { lines: resultLines, range: [usingStartLine, usingEndLine], linesInserted: usingLines.length };\r\n}\r\n\r\n/**\r\n * Insert new test methods after the last existing test method in the file.\r\n * Falls back to inserting after the test-class opening brace when no methods exist.\r\n */\r\nfunction insertTestMethods(\r\n resultLines: string[],\r\n testMethods: string | undefined,\r\n baseIndent: string,\r\n originalLines: string[],\r\n offset: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number; insertEnd: number } {\r\n if (!testMethods?.trim()) {\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n\r\n const normalizedTestMethods = testMethods.replace(/\\r\\n/g, '\\n');\r\n const testMethodBlocks = extractTestMethodBlocks(normalizedTestMethods);\r\n const existingTestMethodNames = collectTestMethodNames(resultLines);\r\n const keptBlocks = testMethodBlocks.filter(block => {\r\n if (!block.methodName) return true;\r\n if (existingTestMethodNames.has(block.methodName)) {\r\n console.log(`Skip duplicate test method: ${block.methodName}`);\r\n return false;\r\n }\r\n existingTestMethodNames.add(block.methodName);\r\n return true;\r\n });\r\n\r\n if (keptBlocks.length === 0) {\r\n console.log('All generated test methods already exist in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n\r\n const indentedBlocks = keptBlocks.map(block => applyIndentation(block.content, baseIndent));\r\n const testMethodLines = indentedBlocks.join('\\n\\n').split('\\n');\r\n\r\n // Find the insertion point in the *original* file (before any offset)\r\n let calculatedInsertLine = findLastTestMethodEndLine(originalLines);\r\n if (calculatedInsertLine === 0) {\r\n calculatedInsertLine = findTestClassInsertPosition(originalLines);\r\n if (calculatedInsertLine === 0) {\r\n console.error('Failed to find insert position for new test methods');\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n console.log('No existing test methods found, inserting after test class opening brace');\r\n }\r\n\r\n const insertMethodAt = calculatedInsertLine - 1 + offset;\r\n\r\n // Prepend an empty line for readability\r\n resultLines.splice(insertMethodAt, 0, '', ...testMethodLines);\r\n\r\n const linesInserted = testMethodLines.length + 1; // +1 for empty line\r\n const methodStartLine = insertMethodAt + 1;\r\n const methodEndLine = insertMethodAt + linesInserted;\r\n const insertEnd = insertMethodAt + linesInserted;\r\n console.log(`Inserted ${linesInserted} lines (including empty line) at index ${insertMethodAt}, range: [${methodStartLine}, ${methodEndLine}]`);\r\n\r\n return { lines: resultLines, range: [methodStartLine, methodEndLine], linesInserted, insertEnd };\r\n}\r\n\r\n/**\r\n * Insert helper / utility code immediately after the newly inserted test methods.\r\n * Falls back to appending after the last test method if no new methods were inserted.\r\n */\r\nfunction insertHelperCode(\r\n resultLines: string[],\r\n helperCode: string | undefined,\r\n baseIndent: string,\r\n originalLines: string[],\r\n offset: number,\r\n testMethodInsertEnd: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number } {\r\n if (!helperCode?.trim()) {\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n const normalizedHelperCode = helperCode.replace(/\\r\\n/g, '\\n');\r\n const helperBlocks = splitTopLevelBlocks(normalizedHelperCode);\r\n const existingMethodNames = collectAllMethodNames(resultLines);\r\n const existingNormalizedContent = normalizeCodeForComparison(resultLines.join('\\n'));\r\n const seenNormalizedFragments = new Set<string>();\r\n\r\n const keptBlocks: string[] = [];\r\n for (const block of helperBlocks) {\r\n const methodName = getMethodNameFromBlock(block);\r\n if (methodName) {\r\n if (existingMethodNames.has(methodName)) {\r\n console.log(`Skip duplicate helper method: ${methodName}`);\r\n continue;\r\n }\r\n existingMethodNames.add(methodName);\r\n keptBlocks.push(block);\r\n continue;\r\n }\r\n\r\n if (containsNormalizedFragment(existingNormalizedContent, block)) {\r\n console.log('Skip duplicate helper non-method block by normalized-content check.');\r\n continue;\r\n }\r\n\r\n const normalizedBlock = normalizeCodeForComparison(block);\r\n if (seenNormalizedFragments.has(normalizedBlock)) {\r\n console.log('Skip duplicate helper non-method block within generated HELPER_CODE.');\r\n continue;\r\n }\r\n seenNormalizedFragments.add(normalizedBlock);\r\n\r\n keptBlocks.push(block);\r\n }\r\n\r\n if (keptBlocks.length === 0) {\r\n console.log('All helper code already exists in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n const indentedHelperCode = keptBlocks.map(block => applyIndentation(block, baseIndent)).join('\\n\\n');\r\n const helperLines = indentedHelperCode.split('\\n');\r\n\r\n // Determine insertion point: right after test methods, or fallback\r\n let insertHelperAt: number;\r\n if (testMethodInsertEnd > 0) {\r\n insertHelperAt = testMethodInsertEnd;\r\n } else {\r\n let helperInsertLine = findLastTestMethodEndLine(originalLines);\r\n if (helperInsertLine === 0) {\r\n helperInsertLine = findTestClassInsertPosition(originalLines);\r\n }\r\n insertHelperAt = helperInsertLine - 1 + offset;\r\n }\r\n\r\n resultLines.splice(insertHelperAt, 0, ...helperLines);\r\n\r\n const helperStartLine = insertHelperAt + 1;\r\n const helperEndLine = insertHelperAt + helperLines.length;\r\n console.log(`Inserted ${helperLines.length} helper code lines at index ${insertHelperAt}, range: [${helperStartLine}, ${helperEndLine}]`);\r\n\r\n return { lines: resultLines, range: [helperStartLine, helperEndLine], linesInserted: helperLines.length };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Parsing & detection helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Parse the structured LLM response into three fenced-code sections:\r\n * `USING_STATEMENTS`, `TEST_METHODS` and `HELPER_CODE`.\r\n *\r\n * Only `TEST_METHODS` is mandatory – the others may be empty.\r\n */\r\nfunction parseGeneratedMoreUtContent(content: string): ParsedMoreUtContent | undefined {\r\n if (!content || content.trim() === '') {\r\n return undefined;\r\n }\r\n\r\n const usingMatch = content.match(/```USING_STATEMENTS\\s*([\\s\\S]*?)```/);\r\n const usingStatements = usingMatch ? usingMatch[1].trim() : '';\r\n\r\n const testMethodsMatch = content.match(/```TEST_METHODS\\s*([\\s\\S]*?)```/);\r\n const testMethods = testMethodsMatch ? testMethodsMatch[1].trim() : '';\r\n\r\n const helperCodeMatch = content.match(/```HELPER_CODE\\s*([\\s\\S]*?)```/);\r\n const helperCode = helperCodeMatch ? helperCodeMatch[1].trim() : '';\r\n\r\n if (!testMethods) {\r\n console.error('Failed to parse generated content: missing TEST_METHODS');\r\n return undefined;\r\n }\r\n\r\n return { usingStatements, testMethods, helperCode };\r\n}\r\n\r\n/**\r\n * Detect the line-ending convention used in the file.\r\n * @returns `'\\r\\n'` for Windows (CRLF) or `'\\n'` for Unix (LF).\r\n */\r\nexport function detectLineEnding(content: string): string {\r\n return content.includes('\\r\\n') ? '\\r\\n' : '\\n';\r\n}\r\n\r\n/**\r\n * Collect all `using` directives already present in the file.\r\n * @returns A `Set` of normalised using strings for O(1) de-duplication.\r\n */\r\nexport function extractExistingUsingStatements(lines: string[]): Set<string> {\r\n const existingUsings = new Set<string>();\r\n for (const line of lines) {\r\n const normalized = normalizeUsingStatement(line);\r\n if (normalized) {\r\n existingUsings.add(normalized);\r\n }\r\n }\r\n return existingUsings;\r\n}\r\n\r\n/**\r\n * Normalise a `using` directive for comparison.\r\n * Strips whitespace and trailing semicolons so that\r\n * `\" using System.Linq ; \"` and `\"using System.Linq\"` match.\r\n *\r\n * @returns `null` when the line is not a using directive.\r\n */\r\nexport function normalizeUsingStatement(line: string): string | null {\r\n const trimmed = line.trim();\r\n if (!trimmed.startsWith('using ') || trimmed.includes('(')) {\r\n return null;\r\n }\r\n return trimmed.replace(/;?\\s*$/, '').replace(/\\s+/g, ' ');\r\n}\r\n\r\n/**\r\n * Detect the indentation level of test methods in the file\r\n * by looking for `[TestMethod]`, `[Test]`, `[Fact]` or `[Theory]` attributes.\r\n *\r\n * Falls back to the first non-empty line inside a class body,\r\n * or 8 spaces if nothing useful is found.\r\n */\r\nexport function detectTestMethodIndent(lines: string[]): string {\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n // Try to match an existing test-method attribute\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n for (const pattern of testMethodPatterns) {\r\n if (pattern.test(line)) {\r\n const match = line.match(/^(\\s*)/);\r\n return match ? match[1] : '';\r\n }\r\n }\r\n }\r\n\r\n // Fallback: use the first non-empty line inside a class body\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?class\\s+/i;\r\n for (let i = 0; i < lines.length; i++) {\r\n if (classPattern.test(lines[i])) {\r\n for (let j = i; j < lines.length; j++) {\r\n if (lines[j].includes('{')) {\r\n for (let k = j + 1; k < lines.length; k++) {\r\n const nextLine = lines[k];\r\n if (nextLine.trim() !== '' && !nextLine.trim().startsWith('}')) {\r\n const match = nextLine.match(/^(\\s*)/);\r\n if (match && match[1].length > 0) {\r\n return match[1];\r\n }\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return ' '; // default: 8 spaces\r\n}\r\n\r\n/**\r\n * Re-indent a block of code so its minimum indentation matches `baseIndent`,\r\n * while preserving the *relative* indentation of nested lines.\r\n */\r\nexport function applyIndentation(code: string, baseIndent: string): string {\r\n const lines = code.split('\\n');\r\n const result: string[] = [];\r\n\r\n // Detect existing minimum indentation\r\n let minIndent = Infinity;\r\n for (const line of lines) {\r\n if (line.trim() === '') continue;\r\n const match = line.match(/^(\\s*)/);\r\n const indent = match ? match[1].length : 0;\r\n if (indent < minIndent) {\r\n minIndent = indent;\r\n }\r\n }\r\n if (minIndent === Infinity) minIndent = 0;\r\n\r\n for (const line of lines) {\r\n if (line.trim() === '') {\r\n result.push('');\r\n } else {\r\n const match = line.match(/^(\\s*)/);\r\n const currentIndent = match ? match[1].length : 0;\r\n const relativeIndent = currentIndent - minIndent;\r\n const newIndent = baseIndent + ' '.repeat(relativeIndent);\r\n result.push(newIndent + line.trim());\r\n }\r\n }\r\n\r\n return result.join('\\n');\r\n}\r\n\r\n/**\r\n * Find the 1-based line number immediately after the last test method's\r\n * closing brace. Returns 0 when no test method is found.\r\n */\r\nexport function findLastTestMethodEndLine(lines: string[]): number {\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n let lastTestMethodStartIndex = -1;\r\n\r\n // Scan backwards for the last test-method attribute\r\n for (let i = lines.length - 1; i >= 0; i--) {\r\n const line = lines[i].trim();\r\n for (const pattern of testMethodPatterns) {\r\n if (pattern.test(line)) {\r\n lastTestMethodStartIndex = i;\r\n break;\r\n }\r\n }\r\n if (lastTestMethodStartIndex !== -1) break;\r\n }\r\n\r\n if (lastTestMethodStartIndex === -1) {\r\n return 0;\r\n }\r\n\r\n // Walk forward tracking brace depth to locate the matching closing brace\r\n // Skips braces inside strings, verbatim strings, char literals, and comments\r\n let braceCount = 0;\r\n let foundOpeningBrace = false;\r\n let inMultiLineComment = false;\r\n\r\n for (let i = lastTestMethodStartIndex; i < lines.length; i++) {\r\n const line = lines[i];\r\n let inString = false;\r\n let inVerbatimString = false;\r\n let inCharLiteral = false;\r\n\r\n for (let j = 0; j < line.length; j++) {\r\n const ch = line[j];\r\n const next = j + 1 < line.length ? line[j + 1] : '';\r\n\r\n // Inside multi-line comment: look for */\r\n if (inMultiLineComment) {\r\n if (ch === '*' && next === '/') {\r\n inMultiLineComment = false;\r\n j++;\r\n }\r\n continue;\r\n }\r\n\r\n // Inside verbatim string: only \"\" (escaped quote) or closing \"\r\n if (inVerbatimString) {\r\n if (ch === '\"') {\r\n if (next === '\"') { j++; } // escaped quote\r\n else { inVerbatimString = false; }\r\n }\r\n continue;\r\n }\r\n\r\n // Inside regular string: handle \\\" escape\r\n if (inString) {\r\n if (ch === '\\\\') { j++; }\r\n else if (ch === '\"') { inString = false; }\r\n continue;\r\n }\r\n\r\n // Inside char literal: handle \\' escape\r\n if (inCharLiteral) {\r\n if (ch === '\\\\') { j++; }\r\n else if (ch === '\\'') { inCharLiteral = false; }\r\n continue;\r\n }\r\n\r\n // Detect start of comments, strings, char literals\r\n if (ch === '/' && next === '/') { break; } // single-line comment: skip rest of line\r\n if (ch === '/' && next === '*') { inMultiLineComment = true; j++; continue; }\r\n if (ch === '@' && next === '\"') { inVerbatimString = true; j++; continue; }\r\n if (ch === '\"') { inString = true; continue; }\r\n if (ch === '\\'') { inCharLiteral = true; continue; }\r\n\r\n // Count braces in actual code\r\n if (ch === '{') {\r\n braceCount++;\r\n foundOpeningBrace = true;\r\n } else if (ch === '}') {\r\n braceCount--;\r\n if (foundOpeningBrace && braceCount === 0) {\r\n return i + 2; // i is 0-based → +1 for 1-based, +1 for *next* line\r\n }\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\n/**\r\n * Find the 1-based line number right after the test class's opening brace.\r\n * Used as a fallback when there are no existing test methods.\r\n */\r\nexport function findTestClassInsertPosition(lines: string[]): number {\r\n const testClassPatterns = [/\\[TestClass\\]/i, /\\[TestFixture\\]/i];\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?class\\s+\\w*Test\\w*/i;\r\n\r\n let testClassAttributeIndex = -1;\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n for (const pattern of testClassPatterns) {\r\n if (pattern.test(line)) {\r\n testClassAttributeIndex = i;\r\n break;\r\n }\r\n }\r\n if (testClassAttributeIndex !== -1) break;\r\n }\r\n\r\n const searchStartIndex = testClassAttributeIndex !== -1 ? testClassAttributeIndex : 0;\r\n let classDeclarationIndex = -1;\r\n\r\n for (let i = searchStartIndex; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (classPattern.test(line) || (testClassAttributeIndex !== -1 && /^\\s*(public\\s+)?(partial\\s+)?class\\s+/i.test(line))) {\r\n classDeclarationIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n if (classDeclarationIndex === -1) {\r\n return 0;\r\n }\r\n\r\n for (let i = classDeclarationIndex; i < lines.length; i++) {\r\n if (lines[i].indexOf('{') !== -1) {\r\n return i + 2; // 0-based → +1 for 1-based, +1 for *next* line\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\nfunction extractTestMethodBlocks(content: string): { methodName: string | null; content: string }[] {\r\n const lines = content.split('\\n');\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n const visitedStarts = new Set<number>();\r\n const blocks: { methodName: string | null; content: string }[] = [];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n const isTestAttr = testMethodPatterns.some(pattern => pattern.test(line));\r\n if (!isTestAttr) continue;\r\n\r\n const range = findTestMethodRangeByBrace(lines, i);\r\n if (!range || visitedStarts.has(range.start)) continue;\r\n visitedStarts.add(range.start);\r\n\r\n const blockLines = lines.slice(range.start, range.end + 1);\r\n let methodName: string | null = null;\r\n for (const blockLine of blockLines) {\r\n const trimmed = blockLine.trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n methodName = extractMethodName(trimmed) || null;\r\n if (methodName) break;\r\n }\r\n\r\n blocks.push({ methodName, content: blockLines.join('\\n') });\r\n }\r\n\r\n if (blocks.length > 0) {\r\n return blocks;\r\n }\r\n\r\n return [{ methodName: null, content }];\r\n}\r\n\r\nfunction collectTestMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n const isTestAttr = testMethodPatterns.some(pattern => pattern.test(line));\r\n if (!isTestAttr) continue;\r\n\r\n const range = findTestMethodRangeByBrace(lines, i);\r\n if (!range) continue;\r\n\r\n for (let j = range.start; j <= range.end; j++) {\r\n const trimmed = lines[j].trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n const name = extractMethodName(trimmed);\r\n if (name) {\r\n names.add(name);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction collectAllMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!isLikelyMethodSignature(trimmed)) continue;\r\n const name = extractMethodName(trimmed);\r\n if (name) names.add(name);\r\n }\r\n return names;\r\n}\r\n\r\nfunction splitTopLevelBlocks(content: string): string[] {\r\n const lines = content.split('\\n');\r\n const blocks: string[] = [];\r\n let current: string[] = [];\r\n let braceDepth = 0;\r\n\r\n const flushCurrent = () => {\r\n if (current.length === 0) return;\r\n const block = current.join('\\n').trim();\r\n if (block) blocks.push(block);\r\n current = [];\r\n };\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n\r\n if (trimmed === '' && current.length === 0) {\r\n continue;\r\n }\r\n\r\n current.push(line);\r\n braceDepth += countChar(line, '{');\r\n braceDepth -= countChar(line, '}');\r\n\r\n if (braceDepth <= 0 && current.length > 0) {\r\n flushCurrent();\r\n braceDepth = 0;\r\n }\r\n }\r\n\r\n flushCurrent();\r\n return blocks;\r\n}\r\n\r\nfunction getMethodNameFromBlock(block: string): string | null {\r\n const lines = block.split('\\n');\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n if (!isLikelyMethodSignature(trimmed)) return null;\r\n const name = extractMethodName(trimmed);\r\n return name || null;\r\n }\r\n return null;\r\n}\r\n\r\nfunction isLikelyMethodSignature(line: string): boolean {\r\n if (!/^(public|private|protected|internal)\\b/.test(line)) return false;\r\n if (/\\b(class|interface|enum|struct|record)\\b/.test(line)) return false;\r\n if (!line.includes('(') || !line.includes(')')) return false;\r\n return true;\r\n}\r\n\r\nfunction normalizeCodeForComparison(code: string): string {\r\n return code\r\n .replace(/\\r\\n/g, '\\n')\r\n .split('\\n')\r\n .map(line => line.trim())\r\n .filter(line => line !== '')\r\n .join('\\n')\r\n .replace(/\\s+/g, ' ')\r\n .trim();\r\n}\r\n\r\nfunction containsNormalizedFragment(existingNormalizedContent: string, fragment: string): boolean {\r\n const normalizedFragment = normalizeCodeForComparison(fragment);\r\n if (!normalizedFragment) {\r\n return true;\r\n }\r\n return existingNormalizedContent.includes(normalizedFragment);\r\n}\r\n\r\nfunction countChar(value: string, target: string): number {\r\n let count = 0;\r\n for (const ch of value) {\r\n if (ch === target) count++;\r\n }\r\n return count;\r\n}\r\n"]}
1
+ {"version":3,"file":"postGenMoreUTProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenMoreUTProcess.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\n\r\nimport { detectUsingInsertPosition, repairXapRequiredNameSpaces, XAP_REQUIRED_USINGS } from \"./repairRequiredNameSpaces\";\r\nimport { XapBondRelatedNamespace } from \"../../types/constants\";\r\nimport { extractMethodName, findTestMethodRangeByBrace } from '../../utils/removeFailedTestMethods';\r\nimport { writeAIRawCode } from '../../utils/writeGenCode';\r\n\r\n/** Result of the post-generation process for additional unit tests */\r\ninterface MoreUTResult {\r\n testCode: string;\r\n insertedRanges: [number, number][];\r\n}\r\n\r\n/** Parsed sections from the LLM-generated content */\r\ninterface ParsedMoreUtContent {\r\n usingStatements: string;\r\n testMethods: string;\r\n helperCode: string;\r\n}\r\n\r\n/**\r\n * Post-process LLM-generated content for the \"more UT\" scenario.\r\n *\r\n * Unlike `postGenProcess` which handles brand-new test files, this function\r\n * merges newly generated test methods, using statements and helper code into\r\n * an **existing** test file. It:\r\n * 1. Parses the structured LLM response (USING_STATEMENTS / TEST_METHODS / HELPER_CODE sections).\r\n * 2. De-duplicates and inserts new `using` directives at the correct position.\r\n * 3. Inserts new test methods right after the last existing test method.\r\n * 4. Appends helper code immediately after the newly inserted test methods.\r\n * 5. Preserves the original line-ending style (CRLF / LF).\r\n *\r\n * @param generatedContent Raw LLM response containing fenced code sections.\r\n * @param testFilePath Absolute path to the existing test file on disk.\r\n * @param isXapCode Whether Xap-specific using directives should be injected.\r\n * @returns An object with the merged test code and the line ranges that were inserted,\r\n * or `undefined` if the generated content could not be parsed.\r\n */\r\nexport function postGenMoreUTProcess(\r\n generatedContent: string,\r\n testFilePath: string,\r\n isXapCode: boolean\r\n): MoreUTResult | undefined {\r\n // Step 1: Parse the structured LLM response\r\n const parsed = parseGeneratedMoreUtContent(generatedContent);\r\n if (!parsed) {\r\n return undefined;\r\n }\r\n\r\n writeAIRawCode(generatedContent, testFilePath);\r\n\r\n const { usingStatements, testMethods, helperCode } = parsed;\r\n\r\n // Step 2: Read and normalise the original test file\r\n const originalTestCode = fs.readFileSync(testFilePath, 'utf-8');\r\n const lineEnding = detectLineEnding(originalTestCode);\r\n const normalizedOriginal = originalTestCode.replace(/\\r\\n/g, '\\n');\r\n const originalLines = normalizedOriginal.split('\\n');\r\n\r\n // Step 3: Detect the indentation convention used in the file\r\n const baseIndent = detectTestMethodIndent(originalLines);\r\n\r\n const insertedRanges: [number, number][] = [];\r\n let resultLines = [...originalLines];\r\n let offset = 0;\r\n\r\n // Step 4: Insert using statements (if any)\r\n const usingResult = insertUsingStatements(\r\n resultLines, usingStatements, isXapCode, testMethods, helperCode, offset\r\n );\r\n resultLines = usingResult.lines;\r\n if (usingResult.range) {\r\n insertedRanges.push(usingResult.range);\r\n }\r\n offset += usingResult.linesInserted;\r\n\r\n // Step 5: Insert new test methods\r\n let testMethodInsertEnd = 0;\r\n const testMethodResult = insertTestMethods(resultLines, testMethods, baseIndent, originalLines, offset);\r\n resultLines = testMethodResult.lines;\r\n if (testMethodResult.range) {\r\n insertedRanges.push(testMethodResult.range);\r\n testMethodInsertEnd = testMethodResult.insertEnd;\r\n }\r\n offset += testMethodResult.linesInserted;\r\n\r\n // Step 6: Insert helper code right after the test methods\r\n const helperResult = insertHelperCode(\r\n resultLines, helperCode, baseIndent, originalLines, offset, testMethodInsertEnd\r\n );\r\n resultLines = helperResult.lines;\r\n if (helperResult.range) {\r\n insertedRanges.push(helperResult.range);\r\n }\r\n\r\n // Step 7: Restore the original line-ending style\r\n let testCode = resultLines.join('\\n').replace(/\\n/g, lineEnding);\r\n \r\n // Step 8: Remove trailing whitespace from each line (trim_trailing_whitespace)\r\n testCode = testCode.split(lineEnding).map(line => line.replace(/\\s+$/, '')).join(lineEnding);\r\n \r\n console.log(`Post generation (more UT) process completed, code length: ${testCode.length}`);\r\n\r\n return { testCode, insertedRanges };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Section inserters – each returns the mutated line array, the inserted range\r\n// and the number of lines added so callers can maintain an offset.\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Insert new `using` directives that don't already exist in the file.\r\n * Also injects Xap-specific usings when `isXapCode` is true.\r\n */\r\nfunction insertUsingStatements(\r\n resultLines: string[],\r\n usingStatements: string | undefined,\r\n isXapCode: boolean,\r\n testMethods: string | undefined,\r\n helperCode: string | undefined,\r\n offset: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number } {\r\n if (!usingStatements?.trim() && !isXapCode) {\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n // Collect all using statements (user-provided + Xap-specific)\r\n let allUsingStatements = usingStatements ? usingStatements.replace(/\\r\\n/g, '\\n') : '';\r\n\r\n if (isXapCode) {\r\n const xapUsings = [...XAP_REQUIRED_USINGS];\r\n // Only add XapBondRelatedNamespace if generated code references XapBlob\r\n if ((testMethods && testMethods.includes('XapBlob')) || (helperCode && helperCode.includes('XapBlob'))) {\r\n xapUsings.push(XapBondRelatedNamespace);\r\n }\r\n const xapUsingsStr = xapUsings.join('\\n');\r\n allUsingStatements = allUsingStatements ? `${allUsingStatements}\\n${xapUsingsStr}` : xapUsingsStr;\r\n }\r\n\r\n // De-duplicate against the original file AND within the merged list itself\r\n const existingUsings = extractExistingUsingStatements(resultLines);\r\n const newUsingLines = allUsingStatements\r\n .split('\\n')\r\n .filter(line => line.trim() !== '')\r\n .filter(line => {\r\n const normalized = normalizeUsingStatement(line);\r\n if (!normalized || existingUsings.has(normalized)) return false;\r\n return existingUsings.add(normalized); // Set.add() returns the Set (truthy)\r\n });\r\n\r\n if (newUsingLines.length === 0) {\r\n console.log('All using statements already exist in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n // Determine where and with what indentation to insert\r\n const { insertIndex: insertUsingAt, indent: usingIndent } = detectUsingInsertPosition(resultLines);\r\n const indentedUsing = applyIndentation(newUsingLines.join('\\n'), usingIndent);\r\n const usingLines = indentedUsing.split('\\n').filter(line => line.trim() !== '');\r\n\r\n const insertIndex = insertUsingAt + offset;\r\n resultLines.splice(insertIndex, 0, ...usingLines);\r\n\r\n const usingStartLine = insertIndex + 1;\r\n const usingEndLine = insertIndex + usingLines.length;\r\n console.log(`Inserted ${usingLines.length} using lines at index ${insertIndex}, range: [${usingStartLine}, ${usingEndLine}]`);\r\n\r\n return { lines: resultLines, range: [usingStartLine, usingEndLine], linesInserted: usingLines.length };\r\n}\r\n\r\n/**\r\n * Insert new test methods after the last existing test method in the file.\r\n * Falls back to inserting after the test-class opening brace when no methods exist.\r\n */\r\nfunction insertTestMethods(\r\n resultLines: string[],\r\n testMethods: string | undefined,\r\n baseIndent: string,\r\n originalLines: string[],\r\n offset: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number; insertEnd: number } {\r\n if (!testMethods?.trim()) {\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n\r\n const normalizedTestMethods = testMethods.replace(/\\r\\n/g, '\\n');\r\n const testMethodBlocks = extractTestMethodBlocks(normalizedTestMethods);\r\n const existingTestMethodNames = collectTestMethodNames(resultLines);\r\n const keptBlocks = testMethodBlocks.filter(block => {\r\n if (!block.methodName) return true;\r\n if (existingTestMethodNames.has(block.methodName)) {\r\n console.log(`Skip duplicate test method: ${block.methodName}`);\r\n return false;\r\n }\r\n existingTestMethodNames.add(block.methodName);\r\n return true;\r\n });\r\n\r\n if (keptBlocks.length === 0) {\r\n console.log('All generated test methods already exist in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n\r\n const indentedBlocks = keptBlocks.map(block => applyIndentation(block.content, baseIndent));\r\n const testMethodLines = indentedBlocks.join('\\n\\n').split('\\n');\r\n\r\n // Find the insertion point in the *original* file (before any offset)\r\n let calculatedInsertLine = findLastTestMethodEndLine(originalLines);\r\n if (calculatedInsertLine === 0) {\r\n calculatedInsertLine = findTestClassInsertPosition(originalLines);\r\n if (calculatedInsertLine === 0) {\r\n console.error('Failed to find insert position for new test methods');\r\n return { lines: resultLines, range: null, linesInserted: 0, insertEnd: 0 };\r\n }\r\n console.log('No existing test methods found, inserting after test class opening brace');\r\n }\r\n\r\n const insertMethodAt = calculatedInsertLine - 1 + offset;\r\n\r\n // Prepend an empty line for readability\r\n resultLines.splice(insertMethodAt, 0, '', ...testMethodLines);\r\n\r\n const linesInserted = testMethodLines.length + 1; // +1 for empty line\r\n const methodStartLine = insertMethodAt + 1;\r\n const methodEndLine = insertMethodAt + linesInserted;\r\n const insertEnd = insertMethodAt + linesInserted;\r\n console.log(`Inserted ${linesInserted} lines (including empty line) at index ${insertMethodAt}, range: [${methodStartLine}, ${methodEndLine}]`);\r\n\r\n return { lines: resultLines, range: [methodStartLine, methodEndLine], linesInserted, insertEnd };\r\n}\r\n\r\n/**\r\n * Insert helper / utility code immediately after the newly inserted test methods.\r\n * Falls back to appending after the last test method if no new methods were inserted.\r\n */\r\nfunction insertHelperCode(\r\n resultLines: string[],\r\n helperCode: string | undefined,\r\n baseIndent: string,\r\n originalLines: string[],\r\n offset: number,\r\n testMethodInsertEnd: number\r\n): { lines: string[]; range: [number, number] | null; linesInserted: number } {\r\n if (!helperCode?.trim()) {\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n const normalizedHelperCode = helperCode.replace(/\\r\\n/g, '\\n');\r\n const helperBlocks = splitTopLevelBlocks(normalizedHelperCode);\r\n const existingMethodNames = collectAllMethodNames(resultLines);\r\n const existingNormalizedContent = normalizeCodeForComparison(resultLines.join('\\n'));\r\n const seenNormalizedFragments = new Set<string>();\r\n\r\n const keptBlocks: string[] = [];\r\n for (const block of helperBlocks) {\r\n const methodName = getMethodNameFromBlock(block);\r\n if (methodName) {\r\n if (existingMethodNames.has(methodName)) {\r\n console.log(`Skip duplicate helper method: ${methodName}`);\r\n continue;\r\n }\r\n existingMethodNames.add(methodName);\r\n keptBlocks.push(block);\r\n continue;\r\n }\r\n\r\n if (containsNormalizedFragment(existingNormalizedContent, block)) {\r\n console.log('Skip duplicate helper non-method block by normalized-content check.');\r\n continue;\r\n }\r\n\r\n const normalizedBlock = normalizeCodeForComparison(block);\r\n if (seenNormalizedFragments.has(normalizedBlock)) {\r\n console.log('Skip duplicate helper non-method block within generated HELPER_CODE.');\r\n continue;\r\n }\r\n seenNormalizedFragments.add(normalizedBlock);\r\n\r\n keptBlocks.push(block);\r\n }\r\n\r\n if (keptBlocks.length === 0) {\r\n console.log('All helper code already exists in the original file, skipping insertion.');\r\n return { lines: resultLines, range: null, linesInserted: 0 };\r\n }\r\n\r\n const indentedHelperCode = keptBlocks.map(block => applyIndentation(block, baseIndent)).join('\\n\\n');\r\n const helperLines = indentedHelperCode.split('\\n');\r\n\r\n // Determine insertion point: right after test methods, or fallback\r\n let insertHelperAt: number;\r\n if (testMethodInsertEnd > 0) {\r\n insertHelperAt = testMethodInsertEnd;\r\n } else {\r\n let helperInsertLine = findLastTestMethodEndLine(originalLines);\r\n if (helperInsertLine === 0) {\r\n helperInsertLine = findTestClassInsertPosition(originalLines);\r\n }\r\n insertHelperAt = helperInsertLine - 1 + offset;\r\n }\r\n\r\n resultLines.splice(insertHelperAt, 0, ...helperLines);\r\n\r\n const helperStartLine = insertHelperAt + 1;\r\n const helperEndLine = insertHelperAt + helperLines.length;\r\n console.log(`Inserted ${helperLines.length} helper code lines at index ${insertHelperAt}, range: [${helperStartLine}, ${helperEndLine}]`);\r\n\r\n return { lines: resultLines, range: [helperStartLine, helperEndLine], linesInserted: helperLines.length };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Parsing & detection helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Parse the structured LLM response into three fenced-code sections:\r\n * `USING_STATEMENTS`, `TEST_METHODS` and `HELPER_CODE`.\r\n *\r\n * Only `TEST_METHODS` is mandatory – the others may be empty.\r\n */\r\nfunction parseGeneratedMoreUtContent(content: string): ParsedMoreUtContent | undefined {\r\n if (!content || content.trim() === '') {\r\n return undefined;\r\n }\r\n\r\n const usingMatch = content.match(/```USING_STATEMENTS\\s*([\\s\\S]*?)```/);\r\n const usingStatements = usingMatch ? usingMatch[1].trim() : '';\r\n\r\n const testMethodsMatch = content.match(/```TEST_METHODS\\s*([\\s\\S]*?)```/);\r\n const testMethods = testMethodsMatch ? testMethodsMatch[1].trim() : '';\r\n\r\n const helperCodeMatch = content.match(/```HELPER_CODE\\s*([\\s\\S]*?)```/);\r\n const helperCode = helperCodeMatch ? helperCodeMatch[1].trim() : '';\r\n\r\n if (!testMethods) {\r\n console.error('Failed to parse generated content: missing TEST_METHODS');\r\n return undefined;\r\n }\r\n\r\n return { usingStatements, testMethods, helperCode };\r\n}\r\n\r\n/**\r\n * Detect the line-ending convention used in the file.\r\n * @returns `'\\r\\n'` for Windows (CRLF) or `'\\n'` for Unix (LF).\r\n */\r\nexport function detectLineEnding(content: string): string {\r\n return content.includes('\\r\\n') ? '\\r\\n' : '\\n';\r\n}\r\n\r\n/**\r\n * Collect all `using` directives already present in the file.\r\n * @returns A `Set` of normalised using strings for O(1) de-duplication.\r\n */\r\nexport function extractExistingUsingStatements(lines: string[]): Set<string> {\r\n const existingUsings = new Set<string>();\r\n for (const line of lines) {\r\n const normalized = normalizeUsingStatement(line);\r\n if (normalized) {\r\n existingUsings.add(normalized);\r\n }\r\n }\r\n return existingUsings;\r\n}\r\n\r\n/**\r\n * Normalise a `using` directive for comparison.\r\n * Strips whitespace and trailing semicolons so that\r\n * `\" using System.Linq ; \"` and `\"using System.Linq\"` match.\r\n *\r\n * @returns `null` when the line is not a using directive.\r\n */\r\nexport function normalizeUsingStatement(line: string): string | null {\r\n const trimmed = line.trim();\r\n if (!trimmed.startsWith('using ') || trimmed.includes('(')) {\r\n return null;\r\n }\r\n return trimmed.replace(/;?\\s*$/, '').replace(/\\s+/g, ' ');\r\n}\r\n\r\n/**\r\n * Detect the indentation level of test methods in the file\r\n * by looking for `[TestMethod]`, `[Test]`, `[Fact]` or `[Theory]` attributes.\r\n *\r\n * Falls back to the first non-empty line inside a class body,\r\n * or 8 spaces if nothing useful is found.\r\n */\r\nexport function detectTestMethodIndent(lines: string[]): string {\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n // Try to match an existing test-method attribute\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n for (const pattern of testMethodPatterns) {\r\n if (pattern.test(line)) {\r\n const match = line.match(/^(\\s*)/);\r\n return match ? match[1] : '';\r\n }\r\n }\r\n }\r\n\r\n // Fallback: use the first non-empty line inside a class body\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?class\\s+/i;\r\n for (let i = 0; i < lines.length; i++) {\r\n if (classPattern.test(lines[i])) {\r\n for (let j = i; j < lines.length; j++) {\r\n if (lines[j].includes('{')) {\r\n for (let k = j + 1; k < lines.length; k++) {\r\n const nextLine = lines[k];\r\n if (nextLine.trim() !== '' && !nextLine.trim().startsWith('}')) {\r\n const match = nextLine.match(/^(\\s*)/);\r\n if (match && match[1].length > 0) {\r\n return match[1];\r\n }\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return ' '; // default: 8 spaces\r\n}\r\n\r\n/**\r\n * Re-indent a block of code so its minimum indentation matches `baseIndent`,\r\n * while preserving the *relative* indentation of nested lines.\r\n */\r\nexport function applyIndentation(code: string, baseIndent: string): string {\r\n const lines = code.split('\\n');\r\n const result: string[] = [];\r\n\r\n // Detect existing minimum indentation\r\n let minIndent = Infinity;\r\n for (const line of lines) {\r\n if (line.trim() === '') continue;\r\n const match = line.match(/^(\\s*)/);\r\n const indent = match ? match[1].length : 0;\r\n if (indent < minIndent) {\r\n minIndent = indent;\r\n }\r\n }\r\n if (minIndent === Infinity) minIndent = 0;\r\n\r\n for (const line of lines) {\r\n if (line.trim() === '') {\r\n result.push('');\r\n } else {\r\n const match = line.match(/^(\\s*)/);\r\n const currentIndent = match ? match[1].length : 0;\r\n const relativeIndent = currentIndent - minIndent;\r\n const newIndent = baseIndent + ' '.repeat(relativeIndent);\r\n result.push(newIndent + line.trim());\r\n }\r\n }\r\n\r\n return result.join('\\n');\r\n}\r\n\r\n/**\r\n * Find the 1-based line number immediately after the last test method's\r\n * closing brace. Returns 0 when no test method is found.\r\n */\r\nexport function findLastTestMethodEndLine(lines: string[]): number {\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n let lastTestMethodStartIndex = -1;\r\n\r\n // Scan backwards for the last test-method attribute\r\n for (let i = lines.length - 1; i >= 0; i--) {\r\n const line = lines[i].trim();\r\n for (const pattern of testMethodPatterns) {\r\n if (pattern.test(line)) {\r\n lastTestMethodStartIndex = i;\r\n break;\r\n }\r\n }\r\n if (lastTestMethodStartIndex !== -1) break;\r\n }\r\n\r\n if (lastTestMethodStartIndex === -1) {\r\n return 0;\r\n }\r\n\r\n // Walk forward tracking brace depth to locate the matching closing brace\r\n // Skips braces inside strings, verbatim strings, char literals, and comments\r\n let braceCount = 0;\r\n let foundOpeningBrace = false;\r\n let inMultiLineComment = false;\r\n\r\n for (let i = lastTestMethodStartIndex; i < lines.length; i++) {\r\n const line = lines[i];\r\n let inString = false;\r\n let inVerbatimString = false;\r\n let inCharLiteral = false;\r\n\r\n for (let j = 0; j < line.length; j++) {\r\n const ch = line[j];\r\n const next = j + 1 < line.length ? line[j + 1] : '';\r\n\r\n // Inside multi-line comment: look for */\r\n if (inMultiLineComment) {\r\n if (ch === '*' && next === '/') {\r\n inMultiLineComment = false;\r\n j++;\r\n }\r\n continue;\r\n }\r\n\r\n // Inside verbatim string: only \"\" (escaped quote) or closing \"\r\n if (inVerbatimString) {\r\n if (ch === '\"') {\r\n if (next === '\"') { j++; } // escaped quote\r\n else { inVerbatimString = false; }\r\n }\r\n continue;\r\n }\r\n\r\n // Inside regular string: handle \\\" escape\r\n if (inString) {\r\n if (ch === '\\\\') { j++; }\r\n else if (ch === '\"') { inString = false; }\r\n continue;\r\n }\r\n\r\n // Inside char literal: handle \\' escape\r\n if (inCharLiteral) {\r\n if (ch === '\\\\') { j++; }\r\n else if (ch === '\\'') { inCharLiteral = false; }\r\n continue;\r\n }\r\n\r\n // Detect start of comments, strings, char literals\r\n if (ch === '/' && next === '/') { break; } // single-line comment: skip rest of line\r\n if (ch === '/' && next === '*') { inMultiLineComment = true; j++; continue; }\r\n if (ch === '@' && next === '\"') { inVerbatimString = true; j++; continue; }\r\n if (ch === '\"') { inString = true; continue; }\r\n if (ch === '\\'') { inCharLiteral = true; continue; }\r\n\r\n // Count braces in actual code\r\n if (ch === '{') {\r\n braceCount++;\r\n foundOpeningBrace = true;\r\n } else if (ch === '}') {\r\n braceCount--;\r\n if (foundOpeningBrace && braceCount === 0) {\r\n return i + 2; // i is 0-based → +1 for 1-based, +1 for *next* line\r\n }\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\n/**\r\n * Find the 1-based line number right after the test class's opening brace.\r\n * Used as a fallback when there are no existing test methods.\r\n */\r\nexport function findTestClassInsertPosition(lines: string[]): number {\r\n const testClassPatterns = [/\\[TestClass\\]/i, /\\[TestFixture\\]/i];\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?class\\s+\\w*Test\\w*/i;\r\n\r\n let testClassAttributeIndex = -1;\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n for (const pattern of testClassPatterns) {\r\n if (pattern.test(line)) {\r\n testClassAttributeIndex = i;\r\n break;\r\n }\r\n }\r\n if (testClassAttributeIndex !== -1) break;\r\n }\r\n\r\n const searchStartIndex = testClassAttributeIndex !== -1 ? testClassAttributeIndex : 0;\r\n let classDeclarationIndex = -1;\r\n\r\n for (let i = searchStartIndex; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (classPattern.test(line) || (testClassAttributeIndex !== -1 && /^\\s*(public\\s+)?(partial\\s+)?class\\s+/i.test(line))) {\r\n classDeclarationIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n if (classDeclarationIndex === -1) {\r\n return 0;\r\n }\r\n\r\n for (let i = classDeclarationIndex; i < lines.length; i++) {\r\n if (lines[i].indexOf('{') !== -1) {\r\n return i + 2; // 0-based → +1 for 1-based, +1 for *next* line\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\nfunction extractTestMethodBlocks(content: string): { methodName: string | null; content: string }[] {\r\n const lines = content.split('\\n');\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n const visitedStarts = new Set<number>();\r\n const blocks: { methodName: string | null; content: string }[] = [];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n const isTestAttr = testMethodPatterns.some(pattern => pattern.test(line));\r\n if (!isTestAttr) continue;\r\n\r\n const range = findTestMethodRangeByBrace(lines, i);\r\n if (!range || visitedStarts.has(range.start)) continue;\r\n visitedStarts.add(range.start);\r\n\r\n const blockLines = lines.slice(range.start, range.end + 1);\r\n let methodName: string | null = null;\r\n for (const blockLine of blockLines) {\r\n const trimmed = blockLine.trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n methodName = extractMethodName(trimmed) || null;\r\n if (methodName) break;\r\n }\r\n\r\n blocks.push({ methodName, content: blockLines.join('\\n') });\r\n }\r\n\r\n if (blocks.length > 0) {\r\n return blocks;\r\n }\r\n\r\n return [{ methodName: null, content }];\r\n}\r\n\r\nfunction collectTestMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n const testMethodPatterns = [\r\n /\\[TestMethod\\]/i,\r\n /\\[Test\\]/i,\r\n /\\[Fact\\]/i,\r\n /\\[Theory\\]/i\r\n ];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n const isTestAttr = testMethodPatterns.some(pattern => pattern.test(line));\r\n if (!isTestAttr) continue;\r\n\r\n const range = findTestMethodRangeByBrace(lines, i);\r\n if (!range) continue;\r\n\r\n for (let j = range.start; j <= range.end; j++) {\r\n const trimmed = lines[j].trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n const name = extractMethodName(trimmed);\r\n if (name) {\r\n names.add(name);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction collectAllMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!isLikelyMethodSignature(trimmed)) continue;\r\n const name = extractMethodName(trimmed);\r\n if (name) names.add(name);\r\n }\r\n return names;\r\n}\r\n\r\nfunction splitTopLevelBlocks(content: string): string[] {\r\n const lines = content.split('\\n');\r\n const blocks: string[] = [];\r\n let current: string[] = [];\r\n let braceDepth = 0;\r\n\r\n const flushCurrent = () => {\r\n if (current.length === 0) return;\r\n const block = current.join('\\n').trim();\r\n if (block) blocks.push(block);\r\n current = [];\r\n };\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n\r\n if (trimmed === '' && current.length === 0) {\r\n continue;\r\n }\r\n\r\n current.push(line);\r\n braceDepth += countChar(line, '{');\r\n braceDepth -= countChar(line, '}');\r\n\r\n if (braceDepth <= 0 && current.length > 0) {\r\n flushCurrent();\r\n braceDepth = 0;\r\n }\r\n }\r\n\r\n flushCurrent();\r\n return blocks;\r\n}\r\n\r\nfunction getMethodNameFromBlock(block: string): string | null {\r\n const lines = block.split('\\n');\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('[')) continue;\r\n if (!isLikelyMethodSignature(trimmed)) return null;\r\n const name = extractMethodName(trimmed);\r\n return name || null;\r\n }\r\n return null;\r\n}\r\n\r\nfunction isLikelyMethodSignature(line: string): boolean {\r\n if (!/^(public|private|protected|internal)\\b/.test(line)) return false;\r\n if (/\\b(class|interface|enum|struct|record)\\b/.test(line)) return false;\r\n if (!line.includes('(') || !line.includes(')')) return false;\r\n return true;\r\n}\r\n\r\nfunction normalizeCodeForComparison(code: string): string {\r\n return code\r\n .replace(/\\r\\n/g, '\\n')\r\n .split('\\n')\r\n .map(line => line.trim())\r\n .filter(line => line !== '')\r\n .join('\\n')\r\n .replace(/\\s+/g, ' ')\r\n .trim();\r\n}\r\n\r\nfunction containsNormalizedFragment(existingNormalizedContent: string, fragment: string): boolean {\r\n const normalizedFragment = normalizeCodeForComparison(fragment);\r\n if (!normalizedFragment) {\r\n return true;\r\n }\r\n return existingNormalizedContent.includes(normalizedFragment);\r\n}\r\n\r\nfunction countChar(value: string, target: string): number {\r\n let count = 0;\r\n for (const ch of value) {\r\n if (ch === target) count++;\r\n }\r\n return count;\r\n}\r\n"]}
@@ -1 +1 @@
1
- export declare function postGenProcess(generatedCode: string, testFramework: string, isXapCode: boolean, sourceCode?: string): string;
1
+ export declare function postGenProcess(generatedCode: string, testFramework: string, isXapCode: boolean, sourceCode?: string, testFilePath?: string): string;
@@ -1,15 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.postGenProcess = postGenProcess;
4
+ const writeGenCode_1 = require("../../utils/writeGenCode");
4
5
  const extractCodeFromResponse_1 = require("./extractCodeFromResponse");
5
6
  const removeSingleLines_1 = require("./removeSingleLines");
6
7
  const repairRequiredNameSpaces_1 = require("./repairRequiredNameSpaces");
7
8
  const validateTestCode_1 = require("./validateTestCode");
8
- function postGenProcess(generatedCode, testFramework, isXapCode, sourceCode) {
9
+ function postGenProcess(generatedCode, testFramework, isXapCode, sourceCode, testFilePath) {
9
10
  if (!isValidTestCode(generatedCode)) {
10
11
  return undefined;
11
12
  }
12
13
  let testCode = (0, extractCodeFromResponse_1.extractCodeFromResponse)(generatedCode);
14
+ (0, writeGenCode_1.writeAIRawCode)(testCode, testFilePath);
13
15
  // testCode = removeTestCodeComments(testCode);
14
16
  testCode = (0, removeSingleLines_1.removeCSharpOnlyLines)(testCode);
15
17
  testCode = (0, repairRequiredNameSpaces_1.repairRequiredNameSpaces)(testCode, testFramework);
@@ -1 +1 @@
1
- {"version":3,"file":"postGenProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenProcess.ts"],"names":[],"mappings":";;AAKA,wCAsBC;AA3BD,uEAAoE;AACpE,2DAA4D;AAC5D,yEAA0H;AAC1H,yDAAsD;AAEtD,SAAgB,cAAc,CAAC,aAAqB,EAAE,aAAqB,EAAE,SAAkB,EAAE,UAAmB;IAChH,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ,GAAG,IAAA,iDAAuB,EAAC,aAAa,CAAC,CAAC;IACtD,+CAA+C;IAC/C,QAAQ,GAAG,IAAA,yCAAqB,EAAC,QAAQ,CAAC,CAAC;IAC3C,QAAQ,GAAG,IAAA,mDAAwB,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,SAAS,EAAE,CAAC;QACZ,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,oDAAoD;IACpD,IAAI,UAAU,EAAE,CAAC;QACb,QAAQ,GAAG,IAAA,gDAAqB,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,wCAAwC;IAExC,OAAO,CAAC,GAAG,CAAC,mDAAmD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC3C,MAAM,aAAa,GAAG,IAAA,sDAA2B,EAAC,QAAQ,CAAC,CAAC;IAC5D,OAAO,aAAa,CAAC;AACzB,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACrC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,CAAC,0BAA0B;IAC5C,CAAC;IACD,0EAA0E;IAC1E,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["import { extractCodeFromResponse } from \"./extractCodeFromResponse\";\r\nimport { removeCSharpOnlyLines } from \"./removeSingleLines\";\r\nimport { repairRequiredNameSpaces, repairXapRequiredNameSpaces, repairUsingStatements } from \"./repairRequiredNameSpaces\";\r\nimport { validateTestCode } from \"./validateTestCode\";\r\n\r\nexport function postGenProcess(generatedCode: string, testFramework: string, isXapCode: boolean, sourceCode?: string): string {\r\n if (!isValidTestCode(generatedCode)) {\r\n return undefined;\r\n }\r\n\r\n let testCode = extractCodeFromResponse(generatedCode);\r\n // testCode = removeTestCodeComments(testCode);\r\n testCode = removeCSharpOnlyLines(testCode);\r\n testCode = repairRequiredNameSpaces(testCode, testFramework);\r\n if (isXapCode) {\r\n testCode = xapCodePostGenProcess(testCode);\r\n }\r\n \r\n // Repair using aliases from source code if provided\r\n if (sourceCode) {\r\n testCode = repairUsingStatements(testCode, sourceCode);\r\n }\r\n\r\n // testCode = addAiAnnotation(testCode);\r\n\r\n console.log(`Post generation process completed, code length: ${testCode.length}`);\r\n return testCode;\r\n}\r\n\r\nfunction xapCodePostGenProcess(testCode: string): string {\r\n const processedCode = repairXapRequiredNameSpaces(testCode);\r\n return processedCode;\r\n}\r\n\r\nfunction isValidTestCode(testCode: string): boolean {\r\n if (!testCode || testCode.trim() === '') {\r\n return false; // Empty code is not valid\r\n }\r\n // Check if the test code contains any test attributes or using statements\r\n const isValid = validateTestCode(testCode);\r\n return isValid;\r\n}\r\n"]}
1
+ {"version":3,"file":"postGenProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenProcess.ts"],"names":[],"mappings":";;AAMA,wCAuBC;AA7BD,2DAA0D;AAC1D,uEAAoE;AACpE,2DAA4D;AAC5D,yEAA0H;AAC1H,yDAAsD;AAEtD,SAAgB,cAAc,CAAC,aAAqB,EAAE,aAAqB,EAAE,SAAkB,EAAE,UAAmB,EAAE,YAAqB;IACvI,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ,GAAG,IAAA,iDAAuB,EAAC,aAAa,CAAC,CAAC;IACtD,IAAA,6BAAc,EAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACvC,+CAA+C;IAC/C,QAAQ,GAAG,IAAA,yCAAqB,EAAC,QAAQ,CAAC,CAAC;IAC3C,QAAQ,GAAG,IAAA,mDAAwB,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,SAAS,EAAE,CAAC;QACZ,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,oDAAoD;IACpD,IAAI,UAAU,EAAE,CAAC;QACb,QAAQ,GAAG,IAAA,gDAAqB,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,wCAAwC;IAExC,OAAO,CAAC,GAAG,CAAC,mDAAmD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC3C,MAAM,aAAa,GAAG,IAAA,sDAA2B,EAAC,QAAQ,CAAC,CAAC;IAC5D,OAAO,aAAa,CAAC;AACzB,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACrC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,CAAC,0BAA0B;IAC5C,CAAC;IACD,0EAA0E;IAC1E,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["import { writeAIRawCode } from \"../../utils/writeGenCode\";\r\nimport { extractCodeFromResponse } from \"./extractCodeFromResponse\";\r\nimport { removeCSharpOnlyLines } from \"./removeSingleLines\";\r\nimport { repairRequiredNameSpaces, repairXapRequiredNameSpaces, repairUsingStatements } from \"./repairRequiredNameSpaces\";\r\nimport { validateTestCode } from \"./validateTestCode\";\r\n\r\nexport function postGenProcess(generatedCode: string, testFramework: string, isXapCode: boolean, sourceCode?: string, testFilePath?: string): string {\r\n if (!isValidTestCode(generatedCode)) {\r\n return undefined;\r\n }\r\n\r\n let testCode = extractCodeFromResponse(generatedCode);\r\n writeAIRawCode(testCode, testFilePath);\r\n // testCode = removeTestCodeComments(testCode);\r\n testCode = removeCSharpOnlyLines(testCode);\r\n testCode = repairRequiredNameSpaces(testCode, testFramework);\r\n if (isXapCode) {\r\n testCode = xapCodePostGenProcess(testCode);\r\n }\r\n \r\n // Repair using aliases from source code if provided\r\n if (sourceCode) {\r\n testCode = repairUsingStatements(testCode, sourceCode);\r\n }\r\n\r\n // testCode = addAiAnnotation(testCode);\r\n\r\n console.log(`Post generation process completed, code length: ${testCode.length}`);\r\n return testCode;\r\n}\r\n\r\nfunction xapCodePostGenProcess(testCode: string): string {\r\n const processedCode = repairXapRequiredNameSpaces(testCode);\r\n return processedCode;\r\n}\r\n\r\nfunction isValidTestCode(testCode: string): boolean {\r\n if (!testCode || testCode.trim() === '') {\r\n return false; // Empty code is not valid\r\n }\r\n // Check if the test code contains any test attributes or using statements\r\n const isValid = validateTestCode(testCode);\r\n return isValid;\r\n}\r\n"]}
@@ -42,6 +42,7 @@ exports.getBuiltDllPath = getBuiltDllPath;
42
42
  const fs = __importStar(require("fs"));
43
43
  const path = __importStar(require("path"));
44
44
  const fast_xml_parser_1 = require("fast-xml-parser");
45
+ const CSPROJ_SLN_MAP_FILE = 'csproj-sln-map.ini';
45
46
  function getSourceFileProjectDir(sourceCodePath) {
46
47
  let currentDir = path.dirname(sourceCodePath);
47
48
  while (currentDir !== path.dirname(currentDir)) {
@@ -98,26 +99,57 @@ function getCodeRepoRoot(csFilePath) {
98
99
  console.log(`No .git folder found in the dir hierarchy of ${csFilePath}. Assuming root is ${rootDir}`);
99
100
  return rootDir;
100
101
  }
101
- /**
102
- * Find the solution file (.sln) by searching upward from the source file path.
103
- */
104
- function findSolutionFile(sourceFilePath) {
105
- const repoRoot = getCodeRepoRoot(sourceFilePath);
106
- let currentDir = path.dirname(sourceFilePath);
102
+ function getCsprojSlnMapPath() {
103
+ return path.resolve(__dirname, '..', 'config', CSPROJ_SLN_MAP_FILE);
104
+ }
105
+ function readCsprojSlnMap(filePath) {
106
+ if (!fs.existsSync(filePath)) {
107
+ return {};
108
+ }
109
+ const content = fs.readFileSync(filePath, 'utf-8');
110
+ const lines = content.split(/\r?\n/);
111
+ const map = {};
112
+ for (const line of lines) {
113
+ const trimmed = line.trim();
114
+ if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith(';')) {
115
+ continue;
116
+ }
117
+ const sepIndex = trimmed.indexOf('=');
118
+ if (sepIndex <= 0) {
119
+ continue;
120
+ }
121
+ const key = trimmed.slice(0, sepIndex).trim();
122
+ const value = trimmed.slice(sepIndex + 1).trim();
123
+ if (key && value) {
124
+ map[key] = value;
125
+ }
126
+ }
127
+ return map;
128
+ }
129
+ function findSlnByName(startDir, repoRoot, slnFileName) {
130
+ let currentDir = startDir;
107
131
  while (true) {
108
132
  const rel = path.relative(repoRoot, currentDir);
109
133
  if (rel.startsWith('..') || path.isAbsolute(rel)) {
110
- break; // currentDir is outside repoRoot
134
+ break;
111
135
  }
112
- try {
113
- const files = fs.readdirSync(currentDir);
114
- const slnFiles = files.filter(file => file.toLowerCase().endsWith('.sln'));
115
- if (slnFiles.length > 0) {
116
- return path.join(currentDir, slnFiles[0]);
136
+ if (slnFileName) {
137
+ const candidate = path.join(currentDir, slnFileName);
138
+ if (fs.existsSync(candidate)) {
139
+ return candidate;
117
140
  }
118
141
  }
119
- catch (error) {
120
- // Skip directories we can't read
142
+ else {
143
+ try {
144
+ const files = fs.readdirSync(currentDir);
145
+ const slnFiles = files.filter(file => file.toLowerCase().endsWith('.sln'));
146
+ if (slnFiles.length > 0) {
147
+ return path.join(currentDir, slnFiles[0]);
148
+ }
149
+ }
150
+ catch (error) {
151
+ // Skip directories we can't read
152
+ }
121
153
  }
122
154
  const parentDir = path.dirname(currentDir);
123
155
  if (parentDir === currentDir) {
@@ -127,6 +159,24 @@ function findSolutionFile(sourceFilePath) {
127
159
  }
128
160
  return null;
129
161
  }
162
+ /**
163
+ * Find the solution file (.sln) by searching upward from the source file path.
164
+ */
165
+ function findSolutionFile(sourceFilePath) {
166
+ const repoRoot = getCodeRepoRoot(sourceFilePath);
167
+ const csprojPath = getSourceFileCsprojFilePath(sourceFilePath);
168
+ const csprojFileName = csprojPath ? path.basename(csprojPath) : null;
169
+ const mapFilePath = getCsprojSlnMapPath();
170
+ const slnMap = csprojFileName ? readCsprojSlnMap(mapFilePath) : {};
171
+ const mappedSlnFileName = csprojFileName ? slnMap[csprojFileName] : undefined;
172
+ if (mappedSlnFileName) {
173
+ const mappedSlnPath = findSlnByName(path.dirname(sourceFilePath), repoRoot, mappedSlnFileName);
174
+ if (mappedSlnPath) {
175
+ return mappedSlnPath;
176
+ }
177
+ }
178
+ return findSlnByName(path.dirname(sourceFilePath), repoRoot);
179
+ }
130
180
  // export function getTestProjectDll(testProjectPath: string) {
131
181
  // const testProjectDir = path.dirname(testProjectPath);
132
182
  // const testProjectName = path.basename(testProjectPath, '.csproj');
@@ -1 +1 @@
1
- {"version":3,"file":"getCodeStructurePath.js","sourceRoot":"","sources":["../../src/utils/getCodeStructurePath.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { XMLParser } from 'fast-xml-parser';\r\n\r\nexport function getSourceFileProjectDir(sourceCodePath: string) {\r\n let currentDir = path.dirname(sourceCodePath);\r\n\r\n while (currentDir !== path.dirname(currentDir)) {\r\n const files = fs.readdirSync(currentDir);\r\n if (files.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n // Check root directory\r\n const rootFiles = fs.readdirSync(currentDir);\r\n if (rootFiles.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n\r\n return null; // No .csproj file found\r\n}\r\n\r\nexport function getSourceFileCsprojFilePath(sourceCodePath: string) {\r\n let currentDir = path.dirname(sourceCodePath);\r\n\r\n while (currentDir !== path.dirname(currentDir)) {\r\n const files = fs.readdirSync(currentDir);\r\n const csprojFilePaths = files.filter(file => file.endsWith('.csproj'));\r\n if (csprojFilePaths?.length > 0) {\r\n return path.join(currentDir, csprojFilePaths[0]);\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n // Check root directory\r\n const rootFiles = fs.readdirSync(currentDir);\r\n if (rootFiles.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n\r\n return null; // No .csproj file found\r\n}\r\n\r\n// export function getSourceFileProjectName(sourceCodePath: string) {\r\n// const projectPath = getSourceFileProjectPath(sourceCodePath);\r\n// if (!projectPath) {\r\n// console.warn(`No .csproj file found for ${sourceCodePath}`);\r\n// return null;\r\n// }\r\n\r\n// const projectName = path.basename(projectPath, '.csproj');\r\n// return projectName;\r\n// }\r\n\r\n// detect .git folder in the dir hierarchy of csFilePath, if exist, it's the code repo root\r\nexport function getCodeRepoRoot(csFilePath: string) {\r\n const rootDir = path.parse(csFilePath).root;\r\n let currentDir = path.dirname(csFilePath);;\r\n\r\n while (currentDir !== rootDir) {\r\n if (fs.existsSync(path.join(currentDir, \".git\"))) {\r\n return currentDir;\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n console.log(`No .git folder found in the dir hierarchy of ${csFilePath}. Assuming root is ${rootDir}`);\r\n return rootDir;\r\n}\r\n\r\n/**\r\n * Find the solution file (.sln) by searching upward from the source file path.\r\n */\r\nexport function findSolutionFile(sourceFilePath: string): string | null {\r\n const repoRoot = getCodeRepoRoot(sourceFilePath);\r\n let currentDir = path.dirname(sourceFilePath);\r\n\r\n while (true) {\r\n const rel = path.relative(repoRoot, currentDir);\r\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\r\n break; // currentDir is outside repoRoot\r\n }\r\n try {\r\n const files = fs.readdirSync(currentDir);\r\n const slnFiles = files.filter(file => file.toLowerCase().endsWith('.sln'));\r\n if (slnFiles.length > 0) {\r\n return path.join(currentDir, slnFiles[0]);\r\n }\r\n } catch (error) {\r\n // Skip directories we can't read\r\n }\r\n \r\n const parentDir = path.dirname(currentDir);\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n currentDir = parentDir;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n// export function getTestProjectDll(testProjectPath: string) {\r\n// const testProjectDir = path.dirname(testProjectPath);\r\n// const testProjectName = path.basename(testProjectPath, '.csproj');\r\n// const dllName = `${testProjectName}.dll`;\r\n// const dllPath = path.join(testProjectDir, 'bin', 'Debug', dllName);\r\n// return dllPath;\r\n// }\r\n\r\n\r\nexport function getAssemblyName(csprojPath: string): string {\r\n const xmlContent = fs.readFileSync(csprojPath, \"utf-8\");\r\n const parser = new XMLParser();\r\n const parsed = parser.parse(xmlContent);\r\n\r\n const project = parsed.Project;\r\n if (!project) {\r\n throw new Error(\"can't parse .csproj 文件\");\r\n }\r\n\r\n const propertyGroups = Array.isArray(project.PropertyGroup)\r\n ? project.PropertyGroup\r\n : [project.PropertyGroup];\r\n\r\n for (const group of propertyGroups) {\r\n if (group.AssemblyName) {\r\n return group.AssemblyName;\r\n }\r\n }\r\n\r\n return path.basename(csprojPath, \".csproj\");\r\n}\r\n\r\nfunction getDllPath(outputDir: string, assemblyName: string): string {\r\n if (!fs.existsSync(outputDir)) {\r\n throw new Error(`The output dir doesn't exist: ${outputDir}`);\r\n }\r\n\r\n // xap dll path: \"D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Tests\\bin\\Debug\\SharedSegments.Tests.dll\"\r\n const dllPath = path.join(outputDir, `${assemblyName}.dll`);\r\n if (fs.existsSync(dllPath)) {\r\n return dllPath;\r\n }\r\n\r\n // general dll path: \"D:\\code\\ai-dev-tools\\csharp-ut-copilot\\CSharpAnalyzer\\CSharpAnalyzer\\bin\\Debug\\net8.0\\CSharpAnalyzer.dll\"\r\n const subdirs = fs.readdirSync(outputDir).filter((f) =>\r\n fs.statSync(path.join(outputDir, f)).isDirectory()\r\n );\r\n\r\n for (const frameworkDir of subdirs) {\r\n const dllPath = path.join(outputDir, frameworkDir, `${assemblyName}.dll`);\r\n if (fs.existsSync(dllPath)) {\r\n return dllPath;\r\n }\r\n }\r\n\r\n throw new Error(`can't get dll file: ${assemblyName}.dll`);\r\n}\r\n\r\nexport function getBuiltDllPath(csprojPath: string): string {\r\n if (!fs.existsSync(csprojPath)) {\r\n throw new Error(`csproj doesn't exist: ${csprojPath}`);\r\n }\r\n\r\n const assemblyName = getAssemblyName(csprojPath);\r\n const projectDir = path.dirname(csprojPath);\r\n const outputBase = path.join(projectDir, \"bin\", \"Debug\");\r\n\r\n return getDllPath(outputBase, assemblyName);\r\n}\r\n\r\n\r\n// const dllPath = getBuiltDllPath(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Tests\\\\SharedSegments.Tests.csproj\");\r\n// console.log(`Test project DLL path: ${dllPath}`);"]}
1
+ {"version":3,"file":"getCodeStructurePath.js","sourceRoot":"","sources":["../../src/utils/getCodeStructurePath.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { XMLParser } from 'fast-xml-parser';\r\n\r\nconst CSPROJ_SLN_MAP_FILE = 'csproj-sln-map.ini';\r\n\r\nexport function getSourceFileProjectDir(sourceCodePath: string) {\r\n let currentDir = path.dirname(sourceCodePath);\r\n\r\n while (currentDir !== path.dirname(currentDir)) {\r\n const files = fs.readdirSync(currentDir);\r\n if (files.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n // Check root directory\r\n const rootFiles = fs.readdirSync(currentDir);\r\n if (rootFiles.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n\r\n return null; // No .csproj file found\r\n}\r\n\r\nexport function getSourceFileCsprojFilePath(sourceCodePath: string) {\r\n let currentDir = path.dirname(sourceCodePath);\r\n\r\n while (currentDir !== path.dirname(currentDir)) {\r\n const files = fs.readdirSync(currentDir);\r\n const csprojFilePaths = files.filter(file => file.endsWith('.csproj'));\r\n if (csprojFilePaths?.length > 0) {\r\n return path.join(currentDir, csprojFilePaths[0]);\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n // Check root directory\r\n const rootFiles = fs.readdirSync(currentDir);\r\n if (rootFiles.some(file => file.endsWith('.csproj'))) {\r\n return currentDir;\r\n }\r\n\r\n return null; // No .csproj file found\r\n}\r\n\r\n// export function getSourceFileProjectName(sourceCodePath: string) {\r\n// const projectPath = getSourceFileProjectPath(sourceCodePath);\r\n// if (!projectPath) {\r\n// console.warn(`No .csproj file found for ${sourceCodePath}`);\r\n// return null;\r\n// }\r\n\r\n// const projectName = path.basename(projectPath, '.csproj');\r\n// return projectName;\r\n// }\r\n\r\n// detect .git folder in the dir hierarchy of csFilePath, if exist, it's the code repo root\r\nexport function getCodeRepoRoot(csFilePath: string) {\r\n const rootDir = path.parse(csFilePath).root;\r\n let currentDir = path.dirname(csFilePath);;\r\n\r\n while (currentDir !== rootDir) {\r\n if (fs.existsSync(path.join(currentDir, \".git\"))) {\r\n return currentDir;\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n console.log(`No .git folder found in the dir hierarchy of ${csFilePath}. Assuming root is ${rootDir}`);\r\n return rootDir;\r\n}\r\n\r\nfunction getCsprojSlnMapPath(): string {\r\n return path.resolve(__dirname, '..', 'config', CSPROJ_SLN_MAP_FILE);\r\n}\r\n\r\nfunction readCsprojSlnMap(filePath: string): Record<string, string> {\r\n if (!fs.existsSync(filePath)) {\r\n return {};\r\n }\r\n\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const lines = content.split(/\\r?\\n/);\r\n const map: Record<string, string> = {};\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith(';')) {\r\n continue;\r\n }\r\n\r\n const sepIndex = trimmed.indexOf('=');\r\n if (sepIndex <= 0) {\r\n continue;\r\n }\r\n\r\n const key = trimmed.slice(0, sepIndex).trim();\r\n const value = trimmed.slice(sepIndex + 1).trim();\r\n if (key && value) {\r\n map[key] = value;\r\n }\r\n }\r\n\r\n return map;\r\n}\r\n\r\nfunction findSlnByName(startDir: string, repoRoot: string, slnFileName?: string): string | null {\r\n let currentDir = startDir;\r\n\r\n while (true) {\r\n const rel = path.relative(repoRoot, currentDir);\r\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\r\n break;\r\n }\r\n\r\n if (slnFileName) {\r\n const candidate = path.join(currentDir, slnFileName);\r\n if (fs.existsSync(candidate)) {\r\n return candidate;\r\n }\r\n } else {\r\n try {\r\n const files = fs.readdirSync(currentDir);\r\n const slnFiles = files.filter(file => file.toLowerCase().endsWith('.sln'));\r\n if (slnFiles.length > 0) {\r\n return path.join(currentDir, slnFiles[0]);\r\n }\r\n } catch (error) {\r\n // Skip directories we can't read\r\n }\r\n }\r\n\r\n const parentDir = path.dirname(currentDir);\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n currentDir = parentDir;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Find the solution file (.sln) by searching upward from the source file path.\r\n */\r\nexport function findSolutionFile(sourceFilePath: string): string | null {\r\n const repoRoot = getCodeRepoRoot(sourceFilePath);\r\n const csprojPath = getSourceFileCsprojFilePath(sourceFilePath);\r\n const csprojFileName = csprojPath ? path.basename(csprojPath) : null;\r\n const mapFilePath = getCsprojSlnMapPath();\r\n const slnMap = csprojFileName ? readCsprojSlnMap(mapFilePath) : {};\r\n const mappedSlnFileName = csprojFileName ? slnMap[csprojFileName] : undefined;\r\n\r\n if (mappedSlnFileName) {\r\n const mappedSlnPath = findSlnByName(path.dirname(sourceFilePath), repoRoot, mappedSlnFileName);\r\n if (mappedSlnPath) {\r\n return mappedSlnPath;\r\n }\r\n }\r\n\r\n return findSlnByName(path.dirname(sourceFilePath), repoRoot);\r\n}\r\n\r\n// export function getTestProjectDll(testProjectPath: string) {\r\n// const testProjectDir = path.dirname(testProjectPath);\r\n// const testProjectName = path.basename(testProjectPath, '.csproj');\r\n// const dllName = `${testProjectName}.dll`;\r\n// const dllPath = path.join(testProjectDir, 'bin', 'Debug', dllName);\r\n// return dllPath;\r\n// }\r\n\r\n\r\nexport function getAssemblyName(csprojPath: string): string {\r\n const xmlContent = fs.readFileSync(csprojPath, \"utf-8\");\r\n const parser = new XMLParser();\r\n const parsed = parser.parse(xmlContent);\r\n\r\n const project = parsed.Project;\r\n if (!project) {\r\n throw new Error(\"can't parse .csproj 文件\");\r\n }\r\n\r\n const propertyGroups = Array.isArray(project.PropertyGroup)\r\n ? project.PropertyGroup\r\n : [project.PropertyGroup];\r\n\r\n for (const group of propertyGroups) {\r\n if (group.AssemblyName) {\r\n return group.AssemblyName;\r\n }\r\n }\r\n\r\n return path.basename(csprojPath, \".csproj\");\r\n}\r\n\r\nfunction getDllPath(outputDir: string, assemblyName: string): string {\r\n if (!fs.existsSync(outputDir)) {\r\n throw new Error(`The output dir doesn't exist: ${outputDir}`);\r\n }\r\n\r\n // xap dll path: \"D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Tests\\bin\\Debug\\SharedSegments.Tests.dll\"\r\n const dllPath = path.join(outputDir, `${assemblyName}.dll`);\r\n if (fs.existsSync(dllPath)) {\r\n return dllPath;\r\n }\r\n\r\n // general dll path: \"D:\\code\\ai-dev-tools\\csharp-ut-copilot\\CSharpAnalyzer\\CSharpAnalyzer\\bin\\Debug\\net8.0\\CSharpAnalyzer.dll\"\r\n const subdirs = fs.readdirSync(outputDir).filter((f) =>\r\n fs.statSync(path.join(outputDir, f)).isDirectory()\r\n );\r\n\r\n for (const frameworkDir of subdirs) {\r\n const dllPath = path.join(outputDir, frameworkDir, `${assemblyName}.dll`);\r\n if (fs.existsSync(dllPath)) {\r\n return dllPath;\r\n }\r\n }\r\n\r\n throw new Error(`can't get dll file: ${assemblyName}.dll`);\r\n}\r\n\r\nexport function getBuiltDllPath(csprojPath: string): string {\r\n if (!fs.existsSync(csprojPath)) {\r\n throw new Error(`csproj doesn't exist: ${csprojPath}`);\r\n }\r\n\r\n const assemblyName = getAssemblyName(csprojPath);\r\n const projectDir = path.dirname(csprojPath);\r\n const outputBase = path.join(projectDir, \"bin\", \"Debug\");\r\n\r\n return getDllPath(outputBase, assemblyName);\r\n}\r\n\r\n\r\n// const dllPath = getBuiltDllPath(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Tests\\\\SharedSegments.Tests.csproj\");\r\n// console.log(`Test project DLL path: ${dllPath}`);"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-dev-tools/csharp-copilot-core",
3
- "version": "0.0.40",
3
+ "version": "0.0.41",
4
4
  "description": "Core library for csharp-copilot",
5
5
  "main": "out/index.js",
6
6
  "typings": "out/index.d.ts",