@ai-dev-tools/csharp-copilot-core 0.0.39 → 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.
- package/out/changedFilesProcessor/processChangedFiles.js +1 -1
- package/out/changedFilesProcessor/processChangedFiles.js.map +1 -1
- package/out/gen/ensureValidLLMResponse.js +1 -1
- package/out/gen/ensureValidLLMResponse.js.map +1 -1
- package/out/gen/postGen/postGenMoreUTAutofixProcess.js +2 -0
- package/out/gen/postGen/postGenMoreUTAutofixProcess.js.map +1 -1
- package/out/gen/postGen/postGenMoreUTProcess.js +5 -1
- package/out/gen/postGen/postGenMoreUTProcess.js.map +1 -1
- package/out/gen/postGen/postGenProcess.d.ts +1 -1
- package/out/gen/postGen/postGenProcess.js +3 -1
- package/out/gen/postGen/postGenProcess.js.map +1 -1
- package/out/utils/getCodeStructurePath.js +64 -14
- package/out/utils/getCodeStructurePath.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 =
|
|
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;
|
|
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}"]}
|
|
@@ -155,6 +155,8 @@ function postGenMoreUTAutofixProcess(generatedCode, testFramework, isXapCode, so
|
|
|
155
155
|
}
|
|
156
156
|
// ── Step 10 : Restore original line-ending style ────────────────────────
|
|
157
157
|
resultCode = resultCode.replace(/\n/g, lineEnding);
|
|
158
|
+
// ── Step 11 : Remove trailing whitespace from each line (trim_trailing_whitespace) ────
|
|
159
|
+
resultCode = resultCode.split(lineEnding).map(line => line.replace(/\s+$/, '')).join(lineEnding);
|
|
158
160
|
console.log(`postGenMoreUTAutofixProcess: completed, code length: ${resultCode.length}`);
|
|
159
161
|
return resultCode;
|
|
160
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postGenMoreUTAutofixProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenMoreUTAutofixProcess.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\n\r\nimport { extractCodeFromResponse } from './extractCodeFromResponse';\r\nimport { removeCSharpOnlyLines } from './removeSingleLines';\r\nimport { repairRequiredNameSpaces, repairXapRequiredNameSpaces, repairUsingStatements } from './repairRequiredNameSpaces';\r\nimport { postGenProcess } from './postGenProcess';\r\nimport {\r\n detectLineEnding,\r\n detectTestMethodIndent,\r\n applyIndentation,\r\n findLastTestMethodEndLine,\r\n findTestClassInsertPosition,\r\n} from './postGenMoreUTProcess';\r\nimport { findTestMethodRangeByBrace, extractMethodName } from '../../utils/removeFailedTestMethods';\r\nimport { writeAIRawCode } from '../../utils/writeGenCode';\r\n\r\n// ─── Types ──────────────────────────────────────────────────────────────────────\r\n\r\ninterface MethodInfo {\r\n name: string;\r\n start: number; // 0-based inclusive\r\n end: number; // 0-based inclusive\r\n}\r\n\r\n// ─── Public entry point ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Post-process LLM response for the \"more UT auto-fix\" scenario.\r\n *\r\n * The LLM is asked to return the **complete** fixed test file, but it sometimes\r\n * omits unchanged test methods. This function performs a *surgical merge*:\r\n *\r\n * 1. Extract & clean the AI code from the markdown response.\r\n * 2. Replace **only** the error test methods in the original file with the\r\n * AI-fixed versions.\r\n * 3. Append any **new** test methods or helper methods that the AI added.\r\n * 4. Replace the `using` block wholesale with the AI's version.\r\n * 5. Apply standard namespace / Xap repairs.\r\n *\r\n * If `errorMethodNames` is empty or `testFilePath` is unavailable the function\r\n * falls back to standard `postGenProcess`-style processing.\r\n */\r\nexport function postGenMoreUTAutofixProcess(\r\n generatedCode: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n sourceCode?: string,\r\n testFilePath?: string,\r\n errorMethodNames?: string[],\r\n): string {\r\n // ── Step 1 : Extract code from the AI response ──────────────────────────\r\n let aiCode = extractCodeFromResponse(generatedCode);\r\n if (!aiCode) {\r\n console.error('postGenMoreUTAutofixProcess: failed to extract code from AI response');\r\n return undefined;\r\n }\r\n aiCode = removeCSharpOnlyLines(aiCode);\r\n\r\n // Write AI raw response to atmpCache for debugging / auditing\r\n writeAIRawCode(aiCode, testFilePath);\r\n\r\n // ── Step 2 : Fallback when surgical merge is not possible ───────────────\r\n if (!errorMethodNames || errorMethodNames.length === 0) {\r\n console.log('postGenMoreUTAutofixProcess: no error method names, returning undefined');\r\n return undefined;\r\n }\r\n if (!testFilePath) {\r\n console.log('postGenMoreUTAutofixProcess: no test file path, returning undefined');\r\n return undefined;\r\n }\r\n if (!fs.existsSync(testFilePath)) {\r\n console.log(`postGenMoreUTAutofixProcess: test file not found (${testFilePath}), returning undefined`);\r\n return undefined;\r\n }\r\n\r\n // ── Step 3 : Read and normalise the original test file ──────────────────\r\n const originalCode = fs.readFileSync(testFilePath, 'utf-8');\r\n const lineEnding = detectLineEnding(originalCode);\r\n\r\n const normalizedAi = aiCode.replace(/\\r\\n/g, '\\n');\r\n const normalizedOriginal = originalCode.replace(/\\r\\n/g, '\\n');\r\n let resultLines = normalizedOriginal.split('\\n');\r\n const aiLines = normalizedAi.split('\\n');\r\n\r\n // ── Step 4 : Enumerate test methods in both files ───────────────────────\r\n const originalMethods = enumerateTestMethods(resultLines);\r\n const aiMethods = enumerateTestMethods(aiLines);\r\n\r\n console.log(`postGenMoreUTAutofixProcess: original has ${originalMethods.length} test method(s), AI has ${aiMethods.length} test method(s)`);\r\n console.log(`postGenMoreUTAutofixProcess: error methods: [${errorMethodNames.join(', ')}]`);\r\n\r\n // ── Step 5 : Replace error methods (bottom-to-top for index stability) ──\r\n // NOTE: This must happen BEFORE replaceUsingBlock, because originalMethods\r\n // indices were computed on the current resultLines. If the using block\r\n // has a different line count the indices would become stale.\r\n const baseIndent = detectTestMethodIndent(resultLines);\r\n\r\n const replacements = errorMethodNames\r\n .map(name => ({\r\n name,\r\n originalRange: originalMethods.find(m => m.name === name),\r\n aiRange: aiMethods.find(m => m.name === name),\r\n }))\r\n .filter(r => r.originalRange && r.aiRange)\r\n .sort((a, b) => b.originalRange.start - a.originalRange.start); // descending\r\n\r\n // If the AI didn't produce any of the error methods, the response is useless — signal retry\r\n if (replacements.length === 0) {\r\n const missingInAi = errorMethodNames.filter(n => !aiMethods.some(m => m.name === n));\r\n console.error(\r\n `postGenMoreUTAutofixProcess: AI response contains none of the ${errorMethodNames.length} ` +\r\n `error method(s), missing: [${missingInAi.join(', ')}]. Returning undefined to trigger retry.`,\r\n );\r\n return undefined;\r\n }\r\n\r\n for (const { name, originalRange, aiRange } of replacements) {\r\n const aiMethodText = aiLines.slice(aiRange.start, aiRange.end + 1);\r\n const reindented = applyIndentation(aiMethodText.join('\\n'), baseIndent).split('\\n');\r\n resultLines.splice(\r\n originalRange.start,\r\n originalRange.end - originalRange.start + 1,\r\n ...reindented,\r\n );\r\n console.log(\r\n ` replaced error method '${name}' (orig ${originalRange.start}-${originalRange.end}) ` +\r\n `with AI fix (${reindented.length} lines)`,\r\n );\r\n }\r\n\r\n // Log any error methods that couldn't be matched\r\n for (const name of errorMethodNames) {\r\n const inOrig = originalMethods.some(m => m.name === name);\r\n const inAi = aiMethods.some(m => m.name === name);\r\n if (!inOrig) console.warn(` error method '${name}' not found in original file`);\r\n if (!inAi) console.warn(` error method '${name}' not found in AI response`);\r\n }\r\n\r\n // ── Step 6 : Replace using block ────────────────────────────────────────\r\n // Done after method replacements so that originalMethods indices stay valid.\r\n resultLines = replaceUsingBlock(resultLines, aiLines);\r\n\r\n // ── Step 7 : Append new test methods from AI ────────────────────────────\r\n const originalMethodNames = new Set(originalMethods.map(m => m.name));\r\n const newTestMethods = aiMethods.filter(m => !originalMethodNames.has(m.name));\r\n\r\n if (newTestMethods.length > 0) {\r\n resultLines = appendMethodBlocks(\r\n resultLines,\r\n aiLines,\r\n newTestMethods,\r\n baseIndent,\r\n 'new test method',\r\n );\r\n }\r\n\r\n // ── Step 8 : Append new helper (non-test) methods from AI ───────────────\r\n const newHelpers = findNewHelperMethods(resultLines, aiLines, aiMethods);\r\n if (newHelpers.length > 0) {\r\n resultLines = appendMethodBlocks(\r\n resultLines,\r\n aiLines,\r\n newHelpers,\r\n baseIndent,\r\n 'new helper method',\r\n );\r\n }\r\n\r\n // ── Step 9 : Standard namespace / Xap / alias repairs ───────────────────\r\n let resultCode = resultLines.join('\\n');\r\n resultCode = repairRequiredNameSpaces(resultCode, testFramework);\r\n if (isXapCode) {\r\n resultCode = repairXapRequiredNameSpaces(resultCode);\r\n }\r\n if (sourceCode) {\r\n resultCode = repairUsingStatements(resultCode, sourceCode);\r\n }\r\n\r\n // ── Step 10 : Restore original line-ending style ────────────────────────\r\n resultCode = resultCode.replace(/\\n/g, lineEnding);\r\n console.log(`postGenMoreUTAutofixProcess: completed, code length: ${resultCode.length}`);\r\n return resultCode;\r\n}\r\n\r\n// ─── Internal helpers ───────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Standard fallback: apply the same processing as `postGenProcess`.\r\n */\r\nfunction fallbackPostProcess(\r\n aiCode: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n sourceCode?: string,\r\n): string {\r\n return postGenProcess(aiCode, testFramework, isXapCode, sourceCode);\r\n}\r\n\r\n/**\r\n * Enumerate all test methods in the file by scanning for test-attribute lines\r\n * and using `findTestMethodRangeByBrace` to determine their full extent\r\n * (including all attributes above the method).\r\n */\r\nfunction enumerateTestMethods(lines: string[]): MethodInfo[] {\r\n const testPatterns = [\r\n /\\[TestMethod/i,\r\n /\\[Test\\]/i,\r\n /\\[Test\\(/i,\r\n /\\[Fact/i,\r\n /\\[Theory/i,\r\n ];\r\n\r\n const methods: MethodInfo[] = [];\r\n const visitedStarts = new Set<number>();\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const trimmed = lines[i].trim();\r\n const isTestAttr = testPatterns.some(p => p.test(trimmed));\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 name = findMethodNameInRange(lines, range.start, range.end);\r\n if (name) {\r\n methods.push({ name, start: range.start, end: range.end });\r\n }\r\n }\r\n\r\n return methods;\r\n}\r\n\r\n/**\r\n * Find the method name within a known method range by skipping attribute /\r\n * empty lines and reading the first real code line.\r\n */\r\nfunction findMethodNameInRange(lines: string[], start: number, end: number): string | null {\r\n for (let i = start; i <= end; i++) {\r\n const trimmed = lines[i].trim();\r\n if (trimmed === '' || trimmed.startsWith('[')) continue;\r\n // First non-attribute, non-empty line is the method signature\r\n const name = extractMethodName(trimmed);\r\n if (name) return name;\r\n }\r\n return null;\r\n}\r\n\r\n// ─── Using-block replacement ────────────────────────────────────────────────────\r\n\r\n/**\r\n * Find the contiguous `using` directive block at the top of the file.\r\n * Returns inclusive 0-based indices, or `null` when no usings are found.\r\n *\r\n * Skips blank lines and single-line comments (`//`) that appear between using\r\n * directives so that groups like:\r\n *\r\n * using System;\r\n * // collections\r\n * using System.Collections.Generic;\r\n *\r\n * are treated as one block.\r\n */\r\nfunction findUsingBlockRange(lines: string[]): { start: number; end: number } | null {\r\n let start = -1;\r\n let end = -1;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const trimmed = lines[i].trim();\r\n\r\n if (isUsingDirective(trimmed)) {\r\n if (start === -1) start = i;\r\n end = i;\r\n } else if (start !== -1) {\r\n // Allow blank lines and single-line comments inside the using block\r\n if (trimmed === '' || trimmed.startsWith('//')) continue;\r\n // Any other content means the using block has ended\r\n break;\r\n }\r\n }\r\n\r\n return start === -1 ? null : { start, end };\r\n}\r\n\r\n/**\r\n * Check whether a trimmed line is a `using` directive (not a `using` statement\r\n * such as `using (var x = ...)`).\r\n */\r\nfunction isUsingDirective(trimmed: string): boolean {\r\n return (trimmed.startsWith('using ') || trimmed.startsWith('using\\t'))\r\n && !trimmed.includes('(')\r\n && trimmed.endsWith(';');\r\n}\r\n\r\n/**\r\n * Replace the original file's using block with the AI response's using block.\r\n * If the AI has no usings the original is returned unchanged.\r\n */\r\nfunction replaceUsingBlock(originalLines: string[], aiLines: string[]): string[] {\r\n const aiRange = findUsingBlockRange(aiLines);\r\n if (!aiRange) return [...originalLines];\r\n\r\n const aiUsings = aiLines.slice(aiRange.start, aiRange.end + 1);\r\n const origRange = findUsingBlockRange(originalLines);\r\n\r\n const result = [...originalLines];\r\n if (origRange) {\r\n result.splice(origRange.start, origRange.end - origRange.start + 1, ...aiUsings);\r\n } else {\r\n // No usings in original – prepend\r\n result.splice(0, 0, ...aiUsings, '');\r\n }\r\n console.log(` replaced using block (${aiUsings.length} lines from AI)`);\r\n return result;\r\n}\r\n\r\n// ─── Appending new method blocks ────────────────────────────────────────────────\r\n\r\n/**\r\n * Append method blocks (described by `methods` referencing `aiLines`) into\r\n * `resultLines` right after the last test method.\r\n */\r\nfunction appendMethodBlocks(\r\n resultLines: string[],\r\n aiLines: string[],\r\n methods: MethodInfo[],\r\n baseIndent: string,\r\n label: string,\r\n): string[] {\r\n let insertLine = findLastTestMethodEndLine(resultLines);\r\n if (insertLine === 0) {\r\n insertLine = findTestClassInsertPosition(resultLines);\r\n }\r\n if (insertLine === 0) {\r\n console.warn(` could not find insert position for ${label}(s), skipping`);\r\n return resultLines;\r\n }\r\n\r\n const insertIndex = insertLine - 1; // 1-based → 0-based\r\n const newLines: string[] = [];\r\n\r\n for (const m of methods) {\r\n const raw = aiLines.slice(m.start, m.end + 1).join('\\n');\r\n const reindented = applyIndentation(raw, baseIndent);\r\n newLines.push('', ...reindented.split('\\n'));\r\n console.log(` appended ${label} '${m.name}' (${m.end - m.start + 1} lines)`);\r\n }\r\n\r\n const result = [...resultLines];\r\n result.splice(insertIndex, 0, ...newLines);\r\n return result;\r\n}\r\n\r\n// ─── New helper method detection ────────────────────────────────────────────────\r\n\r\n/**\r\n * Find non-test methods in the AI response that do **not** exist in the\r\n * original / result file. These are typically helper or factory methods that\r\n * the AI introduced to support the fixed test code.\r\n *\r\n * Detection strategy:\r\n * 1. Mark every line in `aiLines` that belongs to a known test method.\r\n * 2. Inside the class body, scan the unclaimed lines for method signatures.\r\n * 3. Brace-match to determine the full method extent.\r\n * 4. Keep only methods whose name does not appear in `resultLines`.\r\n */\r\nfunction findNewHelperMethods(\r\n resultLines: string[],\r\n aiLines: string[],\r\n aiTestMethods: MethodInfo[],\r\n): MethodInfo[] {\r\n // Lines already claimed by test methods\r\n const claimed = new Set<number>();\r\n for (const m of aiTestMethods) {\r\n for (let i = m.start; i <= m.end; i++) claimed.add(i);\r\n }\r\n\r\n // Approximate class body range in AI: from first `{` after a `class` keyword\r\n // to the matching `}`.\r\n const classBody = findClassBodyRange(aiLines);\r\n if (!classBody) return [];\r\n\r\n // Collect existing method names from the result file for comparison\r\n const existingNames = collectAllMethodNames(resultLines);\r\n\r\n const methodSigPattern = /^\\s*(public|private|protected|internal)\\s+/;\r\n const helpers: MethodInfo[] = [];\r\n const attributePattern = /^\\s*\\[.+\\]\\s*$/;\r\n\r\n for (let i = classBody.start; i <= classBody.end; i++) {\r\n if (claimed.has(i)) continue;\r\n const line = aiLines[i];\r\n if (!methodSigPattern.test(line)) continue;\r\n\r\n // Must look like a method: name followed by `(`\r\n const name = extractMethodName(line.trim());\r\n if (!name || existingNames.has(name)) continue;\r\n\r\n // Check this isn't a property (contains `{ get` or `{ set` on same/next line)\r\n if (isPropertyDeclaration(aiLines, i)) continue;\r\n\r\n // Brace-match to find method end\r\n const end = braceMatchForward(aiLines, i, classBody.end);\r\n if (end === -1) continue;\r\n\r\n // Search upward for preceding attributes\r\n let start = i;\r\n for (let k = i - 1; k >= classBody.start; k--) {\r\n const t = aiLines[k].trim();\r\n if (attributePattern.test(t)) { start = k; }\r\n else if (t === '') { /* skip blank lines between attrs */ }\r\n else break;\r\n }\r\n\r\n helpers.push({ name, start, end });\r\n\r\n // Mark as claimed so we don't double-count\r\n for (let k = start; k <= end; k++) claimed.add(k);\r\n }\r\n\r\n return helpers;\r\n}\r\n\r\n/**\r\n * Find the class body range (the lines between the opening `{` of the test\r\n * class and its matching `}`). Returns 0-based inclusive indices.\r\n */\r\nfunction findClassBodyRange(lines: string[]): { start: number; end: number } | null {\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?(static\\s+)?class\\s+/i;\r\n\r\n let classLineIdx = -1;\r\n for (let i = 0; i < lines.length; i++) {\r\n if (classPattern.test(lines[i])) { classLineIdx = i; break; }\r\n }\r\n if (classLineIdx === -1) return null;\r\n\r\n // Find opening brace\r\n let openIdx = -1;\r\n for (let i = classLineIdx; i < lines.length; i++) {\r\n if (lines[i].includes('{')) { openIdx = i; break; }\r\n }\r\n if (openIdx === -1) return null;\r\n\r\n // Brace-match to find the class closing brace\r\n let depth = 0;\r\n let closeIdx = -1;\r\n for (let i = openIdx; i < lines.length; i++) {\r\n for (const ch of lines[i]) {\r\n if (ch === '{') depth++;\r\n if (ch === '}') { depth--; if (depth === 0) { closeIdx = i; break; } }\r\n }\r\n if (closeIdx !== -1) break;\r\n }\r\n if (closeIdx === -1) return null;\r\n\r\n return { start: openIdx + 1, end: closeIdx - 1 };\r\n}\r\n\r\n/**\r\n * Collect all method-like names from a file (test + non-test) for de-duplication.\r\n */\r\nfunction collectAllMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n const methodSigPattern = /^\\s*(public|private|protected|internal)\\s+/;\r\n\r\n for (const line of lines) {\r\n if (!methodSigPattern.test(line)) continue;\r\n if (isLikelyFieldOrProperty(line)) continue;\r\n const name = extractMethodName(line.trim());\r\n if (name) names.add(name);\r\n }\r\n return names;\r\n}\r\n\r\n/** Simple heuristic to skip field or property declarations. */\r\nfunction isLikelyFieldOrProperty(line: string): boolean {\r\n const trimmed = line.trim();\r\n // Properties: `public int Foo { get; set; }`\r\n if (/\\{\\s*(get|set)/.test(trimmed)) return true;\r\n // Fields: `private readonly int _foo;` or `private int foo = ...;`\r\n if (trimmed.endsWith(';') && !trimmed.includes('(')) return true;\r\n return false;\r\n}\r\n\r\n/** Check whether line `i` starts a property (has `{ get` or `{ set`). */\r\nfunction isPropertyDeclaration(lines: string[], i: number): boolean {\r\n // Check current line and next line for property-style braces\r\n for (let k = i; k < Math.min(i + 3, lines.length); k++) {\r\n if (/\\{\\s*(get|set)/.test(lines[k])) return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Forward brace-match starting from line `start`. Returns the 0-based line\r\n * index of the closing `}`, or -1 on failure.\r\n */\r\nfunction braceMatchForward(lines: string[], start: number, maxLine: number): number {\r\n let depth = 0;\r\n let foundOpen = false;\r\n\r\n for (let i = start; i <= maxLine; i++) {\r\n for (const ch of lines[i]) {\r\n if (ch === '{') { depth++; foundOpen = true; }\r\n if (ch === '}') {\r\n depth--;\r\n if (foundOpen && depth === 0) return i;\r\n }\r\n }\r\n }\r\n return -1;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"postGenMoreUTAutofixProcess.js","sourceRoot":"","sources":["../../../src/gen/postGen/postGenMoreUTAutofixProcess.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\n\r\nimport { extractCodeFromResponse } from './extractCodeFromResponse';\r\nimport { removeCSharpOnlyLines } from './removeSingleLines';\r\nimport { repairRequiredNameSpaces, repairXapRequiredNameSpaces, repairUsingStatements } from './repairRequiredNameSpaces';\r\nimport { postGenProcess } from './postGenProcess';\r\nimport {\r\n detectLineEnding,\r\n detectTestMethodIndent,\r\n applyIndentation,\r\n findLastTestMethodEndLine,\r\n findTestClassInsertPosition,\r\n} from './postGenMoreUTProcess';\r\nimport { findTestMethodRangeByBrace, extractMethodName } from '../../utils/removeFailedTestMethods';\r\nimport { writeAIRawCode } from '../../utils/writeGenCode';\r\n\r\n// ─── Types ──────────────────────────────────────────────────────────────────────\r\n\r\ninterface MethodInfo {\r\n name: string;\r\n start: number; // 0-based inclusive\r\n end: number; // 0-based inclusive\r\n}\r\n\r\n// ─── Public entry point ─────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Post-process LLM response for the \"more UT auto-fix\" scenario.\r\n *\r\n * The LLM is asked to return the **complete** fixed test file, but it sometimes\r\n * omits unchanged test methods. This function performs a *surgical merge*:\r\n *\r\n * 1. Extract & clean the AI code from the markdown response.\r\n * 2. Replace **only** the error test methods in the original file with the\r\n * AI-fixed versions.\r\n * 3. Append any **new** test methods or helper methods that the AI added.\r\n * 4. Replace the `using` block wholesale with the AI's version.\r\n * 5. Apply standard namespace / Xap repairs.\r\n *\r\n * If `errorMethodNames` is empty or `testFilePath` is unavailable the function\r\n * falls back to standard `postGenProcess`-style processing.\r\n */\r\nexport function postGenMoreUTAutofixProcess(\r\n generatedCode: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n sourceCode?: string,\r\n testFilePath?: string,\r\n errorMethodNames?: string[],\r\n): string {\r\n // ── Step 1 : Extract code from the AI response ──────────────────────────\r\n let aiCode = extractCodeFromResponse(generatedCode);\r\n if (!aiCode) {\r\n console.error('postGenMoreUTAutofixProcess: failed to extract code from AI response');\r\n return undefined;\r\n }\r\n aiCode = removeCSharpOnlyLines(aiCode);\r\n\r\n // Write AI raw response to atmpCache for debugging / auditing\r\n writeAIRawCode(aiCode, testFilePath);\r\n\r\n // ── Step 2 : Fallback when surgical merge is not possible ───────────────\r\n if (!errorMethodNames || errorMethodNames.length === 0) {\r\n console.log('postGenMoreUTAutofixProcess: no error method names, returning undefined');\r\n return undefined;\r\n }\r\n if (!testFilePath) {\r\n console.log('postGenMoreUTAutofixProcess: no test file path, returning undefined');\r\n return undefined;\r\n }\r\n if (!fs.existsSync(testFilePath)) {\r\n console.log(`postGenMoreUTAutofixProcess: test file not found (${testFilePath}), returning undefined`);\r\n return undefined;\r\n }\r\n\r\n // ── Step 3 : Read and normalise the original test file ──────────────────\r\n const originalCode = fs.readFileSync(testFilePath, 'utf-8');\r\n const lineEnding = detectLineEnding(originalCode);\r\n\r\n const normalizedAi = aiCode.replace(/\\r\\n/g, '\\n');\r\n const normalizedOriginal = originalCode.replace(/\\r\\n/g, '\\n');\r\n let resultLines = normalizedOriginal.split('\\n');\r\n const aiLines = normalizedAi.split('\\n');\r\n\r\n // ── Step 4 : Enumerate test methods in both files ───────────────────────\r\n const originalMethods = enumerateTestMethods(resultLines);\r\n const aiMethods = enumerateTestMethods(aiLines);\r\n\r\n console.log(`postGenMoreUTAutofixProcess: original has ${originalMethods.length} test method(s), AI has ${aiMethods.length} test method(s)`);\r\n console.log(`postGenMoreUTAutofixProcess: error methods: [${errorMethodNames.join(', ')}]`);\r\n\r\n // ── Step 5 : Replace error methods (bottom-to-top for index stability) ──\r\n // NOTE: This must happen BEFORE replaceUsingBlock, because originalMethods\r\n // indices were computed on the current resultLines. If the using block\r\n // has a different line count the indices would become stale.\r\n const baseIndent = detectTestMethodIndent(resultLines);\r\n\r\n const replacements = errorMethodNames\r\n .map(name => ({\r\n name,\r\n originalRange: originalMethods.find(m => m.name === name),\r\n aiRange: aiMethods.find(m => m.name === name),\r\n }))\r\n .filter(r => r.originalRange && r.aiRange)\r\n .sort((a, b) => b.originalRange.start - a.originalRange.start); // descending\r\n\r\n // If the AI didn't produce any of the error methods, the response is useless — signal retry\r\n if (replacements.length === 0) {\r\n const missingInAi = errorMethodNames.filter(n => !aiMethods.some(m => m.name === n));\r\n console.error(\r\n `postGenMoreUTAutofixProcess: AI response contains none of the ${errorMethodNames.length} ` +\r\n `error method(s), missing: [${missingInAi.join(', ')}]. Returning undefined to trigger retry.`,\r\n );\r\n return undefined;\r\n }\r\n\r\n for (const { name, originalRange, aiRange } of replacements) {\r\n const aiMethodText = aiLines.slice(aiRange.start, aiRange.end + 1);\r\n const reindented = applyIndentation(aiMethodText.join('\\n'), baseIndent).split('\\n');\r\n resultLines.splice(\r\n originalRange.start,\r\n originalRange.end - originalRange.start + 1,\r\n ...reindented,\r\n );\r\n console.log(\r\n ` replaced error method '${name}' (orig ${originalRange.start}-${originalRange.end}) ` +\r\n `with AI fix (${reindented.length} lines)`,\r\n );\r\n }\r\n\r\n // Log any error methods that couldn't be matched\r\n for (const name of errorMethodNames) {\r\n const inOrig = originalMethods.some(m => m.name === name);\r\n const inAi = aiMethods.some(m => m.name === name);\r\n if (!inOrig) console.warn(` error method '${name}' not found in original file`);\r\n if (!inAi) console.warn(` error method '${name}' not found in AI response`);\r\n }\r\n\r\n // ── Step 6 : Replace using block ────────────────────────────────────────\r\n // Done after method replacements so that originalMethods indices stay valid.\r\n resultLines = replaceUsingBlock(resultLines, aiLines);\r\n\r\n // ── Step 7 : Append new test methods from AI ────────────────────────────\r\n const originalMethodNames = new Set(originalMethods.map(m => m.name));\r\n const newTestMethods = aiMethods.filter(m => !originalMethodNames.has(m.name));\r\n\r\n if (newTestMethods.length > 0) {\r\n resultLines = appendMethodBlocks(\r\n resultLines,\r\n aiLines,\r\n newTestMethods,\r\n baseIndent,\r\n 'new test method',\r\n );\r\n }\r\n\r\n // ── Step 8 : Append new helper (non-test) methods from AI ───────────────\r\n const newHelpers = findNewHelperMethods(resultLines, aiLines, aiMethods);\r\n if (newHelpers.length > 0) {\r\n resultLines = appendMethodBlocks(\r\n resultLines,\r\n aiLines,\r\n newHelpers,\r\n baseIndent,\r\n 'new helper method',\r\n );\r\n }\r\n\r\n // ── Step 9 : Standard namespace / Xap / alias repairs ───────────────────\r\n let resultCode = resultLines.join('\\n');\r\n resultCode = repairRequiredNameSpaces(resultCode, testFramework);\r\n if (isXapCode) {\r\n resultCode = repairXapRequiredNameSpaces(resultCode);\r\n }\r\n if (sourceCode) {\r\n resultCode = repairUsingStatements(resultCode, sourceCode);\r\n }\r\n\r\n // ── Step 10 : Restore original line-ending style ────────────────────────\r\n resultCode = resultCode.replace(/\\n/g, lineEnding);\r\n \r\n // ── Step 11 : Remove trailing whitespace from each line (trim_trailing_whitespace) ────\r\n resultCode = resultCode.split(lineEnding).map(line => line.replace(/\\s+$/, '')).join(lineEnding);\r\n \r\n console.log(`postGenMoreUTAutofixProcess: completed, code length: ${resultCode.length}`);\r\n return resultCode;\r\n}\r\n\r\n// ─── Internal helpers ───────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Standard fallback: apply the same processing as `postGenProcess`.\r\n */\r\nfunction fallbackPostProcess(\r\n aiCode: string,\r\n testFramework: string,\r\n isXapCode: boolean,\r\n sourceCode?: string,\r\n): string {\r\n return postGenProcess(aiCode, testFramework, isXapCode, sourceCode);\r\n}\r\n\r\n/**\r\n * Enumerate all test methods in the file by scanning for test-attribute lines\r\n * and using `findTestMethodRangeByBrace` to determine their full extent\r\n * (including all attributes above the method).\r\n */\r\nfunction enumerateTestMethods(lines: string[]): MethodInfo[] {\r\n const testPatterns = [\r\n /\\[TestMethod/i,\r\n /\\[Test\\]/i,\r\n /\\[Test\\(/i,\r\n /\\[Fact/i,\r\n /\\[Theory/i,\r\n ];\r\n\r\n const methods: MethodInfo[] = [];\r\n const visitedStarts = new Set<number>();\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const trimmed = lines[i].trim();\r\n const isTestAttr = testPatterns.some(p => p.test(trimmed));\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 name = findMethodNameInRange(lines, range.start, range.end);\r\n if (name) {\r\n methods.push({ name, start: range.start, end: range.end });\r\n }\r\n }\r\n\r\n return methods;\r\n}\r\n\r\n/**\r\n * Find the method name within a known method range by skipping attribute /\r\n * empty lines and reading the first real code line.\r\n */\r\nfunction findMethodNameInRange(lines: string[], start: number, end: number): string | null {\r\n for (let i = start; i <= end; i++) {\r\n const trimmed = lines[i].trim();\r\n if (trimmed === '' || trimmed.startsWith('[')) continue;\r\n // First non-attribute, non-empty line is the method signature\r\n const name = extractMethodName(trimmed);\r\n if (name) return name;\r\n }\r\n return null;\r\n}\r\n\r\n// ─── Using-block replacement ────────────────────────────────────────────────────\r\n\r\n/**\r\n * Find the contiguous `using` directive block at the top of the file.\r\n * Returns inclusive 0-based indices, or `null` when no usings are found.\r\n *\r\n * Skips blank lines and single-line comments (`//`) that appear between using\r\n * directives so that groups like:\r\n *\r\n * using System;\r\n * // collections\r\n * using System.Collections.Generic;\r\n *\r\n * are treated as one block.\r\n */\r\nfunction findUsingBlockRange(lines: string[]): { start: number; end: number } | null {\r\n let start = -1;\r\n let end = -1;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const trimmed = lines[i].trim();\r\n\r\n if (isUsingDirective(trimmed)) {\r\n if (start === -1) start = i;\r\n end = i;\r\n } else if (start !== -1) {\r\n // Allow blank lines and single-line comments inside the using block\r\n if (trimmed === '' || trimmed.startsWith('//')) continue;\r\n // Any other content means the using block has ended\r\n break;\r\n }\r\n }\r\n\r\n return start === -1 ? null : { start, end };\r\n}\r\n\r\n/**\r\n * Check whether a trimmed line is a `using` directive (not a `using` statement\r\n * such as `using (var x = ...)`).\r\n */\r\nfunction isUsingDirective(trimmed: string): boolean {\r\n return (trimmed.startsWith('using ') || trimmed.startsWith('using\\t'))\r\n && !trimmed.includes('(')\r\n && trimmed.endsWith(';');\r\n}\r\n\r\n/**\r\n * Replace the original file's using block with the AI response's using block.\r\n * If the AI has no usings the original is returned unchanged.\r\n */\r\nfunction replaceUsingBlock(originalLines: string[], aiLines: string[]): string[] {\r\n const aiRange = findUsingBlockRange(aiLines);\r\n if (!aiRange) return [...originalLines];\r\n\r\n const aiUsings = aiLines.slice(aiRange.start, aiRange.end + 1);\r\n const origRange = findUsingBlockRange(originalLines);\r\n\r\n const result = [...originalLines];\r\n if (origRange) {\r\n result.splice(origRange.start, origRange.end - origRange.start + 1, ...aiUsings);\r\n } else {\r\n // No usings in original – prepend\r\n result.splice(0, 0, ...aiUsings, '');\r\n }\r\n console.log(` replaced using block (${aiUsings.length} lines from AI)`);\r\n return result;\r\n}\r\n\r\n// ─── Appending new method blocks ────────────────────────────────────────────────\r\n\r\n/**\r\n * Append method blocks (described by `methods` referencing `aiLines`) into\r\n * `resultLines` right after the last test method.\r\n */\r\nfunction appendMethodBlocks(\r\n resultLines: string[],\r\n aiLines: string[],\r\n methods: MethodInfo[],\r\n baseIndent: string,\r\n label: string,\r\n): string[] {\r\n let insertLine = findLastTestMethodEndLine(resultLines);\r\n if (insertLine === 0) {\r\n insertLine = findTestClassInsertPosition(resultLines);\r\n }\r\n if (insertLine === 0) {\r\n console.warn(` could not find insert position for ${label}(s), skipping`);\r\n return resultLines;\r\n }\r\n\r\n const insertIndex = insertLine - 1; // 1-based → 0-based\r\n const newLines: string[] = [];\r\n\r\n for (const m of methods) {\r\n const raw = aiLines.slice(m.start, m.end + 1).join('\\n');\r\n const reindented = applyIndentation(raw, baseIndent);\r\n newLines.push('', ...reindented.split('\\n'));\r\n console.log(` appended ${label} '${m.name}' (${m.end - m.start + 1} lines)`);\r\n }\r\n\r\n const result = [...resultLines];\r\n result.splice(insertIndex, 0, ...newLines);\r\n return result;\r\n}\r\n\r\n// ─── New helper method detection ────────────────────────────────────────────────\r\n\r\n/**\r\n * Find non-test methods in the AI response that do **not** exist in the\r\n * original / result file. These are typically helper or factory methods that\r\n * the AI introduced to support the fixed test code.\r\n *\r\n * Detection strategy:\r\n * 1. Mark every line in `aiLines` that belongs to a known test method.\r\n * 2. Inside the class body, scan the unclaimed lines for method signatures.\r\n * 3. Brace-match to determine the full method extent.\r\n * 4. Keep only methods whose name does not appear in `resultLines`.\r\n */\r\nfunction findNewHelperMethods(\r\n resultLines: string[],\r\n aiLines: string[],\r\n aiTestMethods: MethodInfo[],\r\n): MethodInfo[] {\r\n // Lines already claimed by test methods\r\n const claimed = new Set<number>();\r\n for (const m of aiTestMethods) {\r\n for (let i = m.start; i <= m.end; i++) claimed.add(i);\r\n }\r\n\r\n // Approximate class body range in AI: from first `{` after a `class` keyword\r\n // to the matching `}`.\r\n const classBody = findClassBodyRange(aiLines);\r\n if (!classBody) return [];\r\n\r\n // Collect existing method names from the result file for comparison\r\n const existingNames = collectAllMethodNames(resultLines);\r\n\r\n const methodSigPattern = /^\\s*(public|private|protected|internal)\\s+/;\r\n const helpers: MethodInfo[] = [];\r\n const attributePattern = /^\\s*\\[.+\\]\\s*$/;\r\n\r\n for (let i = classBody.start; i <= classBody.end; i++) {\r\n if (claimed.has(i)) continue;\r\n const line = aiLines[i];\r\n if (!methodSigPattern.test(line)) continue;\r\n\r\n // Must look like a method: name followed by `(`\r\n const name = extractMethodName(line.trim());\r\n if (!name || existingNames.has(name)) continue;\r\n\r\n // Check this isn't a property (contains `{ get` or `{ set` on same/next line)\r\n if (isPropertyDeclaration(aiLines, i)) continue;\r\n\r\n // Brace-match to find method end\r\n const end = braceMatchForward(aiLines, i, classBody.end);\r\n if (end === -1) continue;\r\n\r\n // Search upward for preceding attributes\r\n let start = i;\r\n for (let k = i - 1; k >= classBody.start; k--) {\r\n const t = aiLines[k].trim();\r\n if (attributePattern.test(t)) { start = k; }\r\n else if (t === '') { /* skip blank lines between attrs */ }\r\n else break;\r\n }\r\n\r\n helpers.push({ name, start, end });\r\n\r\n // Mark as claimed so we don't double-count\r\n for (let k = start; k <= end; k++) claimed.add(k);\r\n }\r\n\r\n return helpers;\r\n}\r\n\r\n/**\r\n * Find the class body range (the lines between the opening `{` of the test\r\n * class and its matching `}`). Returns 0-based inclusive indices.\r\n */\r\nfunction findClassBodyRange(lines: string[]): { start: number; end: number } | null {\r\n const classPattern = /^\\s*(public\\s+)?(partial\\s+)?(static\\s+)?class\\s+/i;\r\n\r\n let classLineIdx = -1;\r\n for (let i = 0; i < lines.length; i++) {\r\n if (classPattern.test(lines[i])) { classLineIdx = i; break; }\r\n }\r\n if (classLineIdx === -1) return null;\r\n\r\n // Find opening brace\r\n let openIdx = -1;\r\n for (let i = classLineIdx; i < lines.length; i++) {\r\n if (lines[i].includes('{')) { openIdx = i; break; }\r\n }\r\n if (openIdx === -1) return null;\r\n\r\n // Brace-match to find the class closing brace\r\n let depth = 0;\r\n let closeIdx = -1;\r\n for (let i = openIdx; i < lines.length; i++) {\r\n for (const ch of lines[i]) {\r\n if (ch === '{') depth++;\r\n if (ch === '}') { depth--; if (depth === 0) { closeIdx = i; break; } }\r\n }\r\n if (closeIdx !== -1) break;\r\n }\r\n if (closeIdx === -1) return null;\r\n\r\n return { start: openIdx + 1, end: closeIdx - 1 };\r\n}\r\n\r\n/**\r\n * Collect all method-like names from a file (test + non-test) for de-duplication.\r\n */\r\nfunction collectAllMethodNames(lines: string[]): Set<string> {\r\n const names = new Set<string>();\r\n const methodSigPattern = /^\\s*(public|private|protected|internal)\\s+/;\r\n\r\n for (const line of lines) {\r\n if (!methodSigPattern.test(line)) continue;\r\n if (isLikelyFieldOrProperty(line)) continue;\r\n const name = extractMethodName(line.trim());\r\n if (name) names.add(name);\r\n }\r\n return names;\r\n}\r\n\r\n/** Simple heuristic to skip field or property declarations. */\r\nfunction isLikelyFieldOrProperty(line: string): boolean {\r\n const trimmed = line.trim();\r\n // Properties: `public int Foo { get; set; }`\r\n if (/\\{\\s*(get|set)/.test(trimmed)) return true;\r\n // Fields: `private readonly int _foo;` or `private int foo = ...;`\r\n if (trimmed.endsWith(';') && !trimmed.includes('(')) return true;\r\n return false;\r\n}\r\n\r\n/** Check whether line `i` starts a property (has `{ get` or `{ set`). */\r\nfunction isPropertyDeclaration(lines: string[], i: number): boolean {\r\n // Check current line and next line for property-style braces\r\n for (let k = i; k < Math.min(i + 3, lines.length); k++) {\r\n if (/\\{\\s*(get|set)/.test(lines[k])) return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Forward brace-match starting from line `start`. Returns the 0-based line\r\n * index of the closing `}`, or -1 on failure.\r\n */\r\nfunction braceMatchForward(lines: string[], start: number, maxLine: number): number {\r\n let depth = 0;\r\n let foundOpen = false;\r\n\r\n for (let i = start; i <= maxLine; i++) {\r\n for (const ch of lines[i]) {\r\n if (ch === '{') { depth++; foundOpen = true; }\r\n if (ch === '}') {\r\n depth--;\r\n if (foundOpen && depth === 0) return i;\r\n }\r\n }\r\n }\r\n return -1;\r\n}\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');
|
|
@@ -103,7 +105,9 @@ function postGenMoreUTProcess(generatedContent, testFilePath, isXapCode) {
|
|
|
103
105
|
insertedRanges.push(helperResult.range);
|
|
104
106
|
}
|
|
105
107
|
// Step 7: Restore the original line-ending style
|
|
106
|
-
|
|
108
|
+
let testCode = resultLines.join('\n').replace(/\n/g, lineEnding);
|
|
109
|
+
// Step 8: Remove trailing whitespace from each line (trim_trailing_whitespace)
|
|
110
|
+
testCode = testCode.split(lineEnding).map(line => line.replace(/\s+$/, '')).join(lineEnding);
|
|
107
111
|
console.log(`Post generation (more UT) process completed, code length: ${testCode.length}`);
|
|
108
112
|
return { testCode, insertedRanges };
|
|
109
113
|
}
|
|
@@ -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 const testCode = resultLines.join('\\n').replace(/\\n/g, lineEnding);\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":";;
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
function
|
|
105
|
-
|
|
106
|
-
|
|
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;
|
|
134
|
+
break;
|
|
111
135
|
}
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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}`);"]}
|