@ai-dev-tools/csharp-copilot-core 0.0.36 → 0.0.38

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.
@@ -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\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\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 => !existingUsings.has(normalizeUsingStatement(line)));\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 indentedTestMethods = applyIndentation(normalizedTestMethods, baseIndent);\r\n const testMethodLines = indentedTestMethods.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 indentedHelperCode = applyIndentation(normalizedHelperCode, baseIndent);\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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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"]}
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\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 indentedTestMethods = applyIndentation(normalizedTestMethods, baseIndent);\r\n const testMethodLines = indentedTestMethods.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 indentedHelperCode = applyIndentation(normalizedHelperCode, baseIndent);\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"]}
@@ -18,6 +18,7 @@ Fix the unit test code that failed to {{failedStage}}. The user will provide the
18
18
  - Only fix the errors mentioned in the error messages.
19
19
  - **Keep existing comments unchanged**. Do NOT add new comments or explanations in the code.
20
20
  - Ensure all `using` statements are at the top of the file.
21
+ - **Keep ALL original `using` statements** from the current test code — non-error test methods may depend on them. Only remove a `using` if it directly causes a build error. You may add new `using` statements if the fix requires them.
21
22
  - Ensure the code has no syntax errors.
22
23
 
23
24
  The following are the guidelines used when generating the test code. You may refer to them when fixing the test code:
@@ -810,7 +810,7 @@ function getOrCreatTestFile(sourceCodePath, testFilePath, changedTestFiles) {
810
810
  }
811
811
  // if outputPath param is not provided, try to find an existing test file
812
812
  // if no existing test file found, create a new one in test project
813
- console.log(' Output path is missing. outputPath:', testFilePath, ', start looking for existing test project');
813
+ console.log(' Output path is missing, start looking for existing test project');
814
814
  // Try to find test file from changed files first
815
815
  let resultFromChangedFiles = getTestFileFromChangedFiles(sourceCodePath, changedTestFiles);
816
816
  if (resultFromChangedFiles.testFilePath) {
@@ -1 +1 @@
1
- {"version":3,"file":"getTestFile.js","sourceRoot":"","sources":["../../src/utils/getTestFile.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { getAssemblyName, getCodeRepoRoot, getSourceFileCsprojFilePath, getSourceFileProjectDir } from './getCodeStructurePath';\r\nimport { getOrCreateDir } from './getOrCreateDir';\r\n\r\nimport { XMLParser } from 'fast-xml-parser';\r\n\r\nconst TEST_NAME_REGEX = /(Test|Tests)/i;\r\nconst TEST_ATTR_REGEX = /\\[(Fact|Theory|TestClass|TestMethod|Test)\\]/;\r\n\r\n/**\r\n * Check if a file path is a test file based on common naming conventions.\r\n * Checks if the file name (without .cs extension) ends with test, tests, unittest, or unittests.\r\n */\r\nexport function isTestFile(filepath: string): boolean {\r\n const fileName = path.basename(filepath).toLowerCase();\r\n const fileNameWithoutExt = fileName.replace(/\\.cs$/, '');\r\n \r\n return fileNameWithoutExt.endsWith('test') || \r\n fileNameWithoutExt.endsWith('tests') ||\r\n fileNameWithoutExt.endsWith('unittest') ||\r\n fileNameWithoutExt.endsWith('unittests');\r\n}\r\n\r\n// Modifier pattern for C# type declarations (sealed, abstract, static, partial)\r\nconst MODIFIER_PATTERN = `(?:sealed|abstract|static|partial)?\\\\s*`;\r\n\r\n// Helper function to create test file name pattern\r\nfunction getTestFileNamePattern(sourceFileName: string): RegExp {\r\n return new RegExp(`^${sourceFileName}(Unit)?(\\\\.)?(Test|Tests)$`);\r\n}\r\n\r\n/**\r\n * Extract words from a name string (e.g., project name, file name)\r\n * Splits by camelCase and special characters, returns lowercase words\r\n * \r\n * @param name - The name string to extract words from\r\n * @returns Array of lowercase words\r\n */\r\nfunction extractWordsFromName(name: string): string[] {\r\n return name\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .split(/[^a-zA-Z0-9]+/)\r\n .filter(Boolean)\r\n .map(w => w.toLowerCase());\r\n}\r\n\r\n/**\r\n * Calculate word-level matching score between two names\r\n * Returns the count of matching words\r\n * \r\n * @param name1 - First name to compare\r\n * @param name2 - Second name to compare\r\n * @returns Number of matching words\r\n */\r\nfunction calculateWordMatchCount(name1: string, name2: string): number {\r\n const words1 = extractWordsFromName(name1);\r\n const words2 = extractWordsFromName(name2);\r\n \r\n const words1Set = new Set(words1);\r\n return words2.filter(w => words1Set.has(w)).length;\r\n}\r\n\r\n/**\r\n * Get all subfolder names under a directory (recursive)\r\n * Skips: bin, obj, .vs directories\r\n * \r\n * @param dirPath - Path to directory\r\n * @returns Set of lowercase folder names\r\n */\r\nfunction getSubfolderNamesRecursive(dirPath: string): Set<string> {\r\n const subfolders = new Set<string>();\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n subfolders.add(entry.name.toLowerCase());\r\n // Recursively get subfolders\r\n const subPath = path.join(dirPath, entry.name);\r\n const deepSubfolders = getSubfolderNamesRecursive(subPath);\r\n deepSubfolders.forEach(f => subfolders.add(f));\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n return subfolders;\r\n}\r\n\r\n/**\r\n * Get all .cs file names under a directory (recursive)\r\n * Skips: bin, obj, .vs directories\r\n * \r\n * @param dirPath - Path to directory\r\n * @returns Set of lowercase file names (without .cs extension)\r\n */\r\nfunction getFileNamesRecursive(dirPath: string): Set<string> {\r\n const fileNames = new Set<string>();\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.name === 'bin' || entry.name === 'obj' || entry.name === '.vs') {\r\n continue;\r\n }\r\n const fullPath = path.join(dirPath, entry.name);\r\n if (entry.isDirectory()) {\r\n // Recursively get file names from subdirectories\r\n const subFileNames = getFileNamesRecursive(fullPath);\r\n subFileNames.forEach(f => fileNames.add(f));\r\n } else if (entry.isFile() && entry.name.endsWith('.cs')) {\r\n // Add file name without .cs extension\r\n fileNames.add(entry.name.slice(0, -3).toLowerCase());\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n return fileNames;\r\n}\r\n\r\nfunction findAllCsprojFiles(dir: string, excludedPaths: string[]): string[] {\r\n const results: string[] = [];\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n if (entry.name === \".vs\" || excludedPaths.includes(fullPath)) {\r\n continue; // Skip excluded paths\r\n }\r\n\r\n if (entry.isDirectory()) {\r\n results.push(...findAllCsprojFiles(fullPath, excludedPaths));\r\n } else if (entry.isFile() && entry.name.endsWith('.csproj')) {\r\n results.push(fullPath);\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nfunction isXapTestProject(csprojPath: string): boolean {\r\n try {\r\n const content = fs.readFileSync(csprojPath, 'utf-8');\r\n const parser = new XMLParser({ ignoreAttributes: false, ignoreDeclaration: true });\r\n const json = parser.parse(content);\r\n const project = json.Project;\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.XapProjectType === 'TestProject') {\r\n return true;\r\n }\r\n }\r\n } catch (err: any) {\r\n console.error(`Failed to parse ${csprojPath}: ${err.message}`);\r\n }\r\n return false;\r\n}\r\n\r\nfunction isGeneralTestProject(csprojPath: string): boolean {\r\n try {\r\n const content = fs.readFileSync(csprojPath, 'utf-8');\r\n\r\n // 1. package reference (test framework)\r\n const referencesTestFramework = /<PackageReference\\s+Include=\"(xunit|nunit|MSTest\\.TestFramework|Microsoft\\.NET\\.Test\\.Sdk)\"/i.test(content);\r\n\r\n // 2. file name *.Tests.csproj\r\n const fileNameHasTests = (/\\.Tests\\.csproj$/i.test(path.basename(csprojPath))) || (/\\.Test\\.csproj$/i.test(path.basename(csprojPath)));\r\n\r\n // 3. path contains Tests\r\n const pathHasTests = /[\\\\/](Tests?|UnitTests?|IntegrationTests?)[\\\\/]/i.test(csprojPath);\r\n\r\n // 4. Project SDK is test type (optional)\r\n const sdkIsTestSdk = /<Project\\s+Sdk=\"Microsoft\\.NET\\.Test\\.Sdk\"/i.test(content);\r\n\r\n // 组合判断\r\n return referencesTestFramework || sdkIsTestSdk || fileNameHasTests || pathHasTests;\r\n } catch (err) {\r\n console.error(`can't read csproj file: ${csprojPath}`);\r\n return false;\r\n }\r\n}\r\n\r\nfunction isFalconUnitTestProject(csprojPath: string): boolean {\r\n const xmlContent = fs.readFileSync(csprojPath, 'utf-8');\r\n\r\n const parser = new XMLParser({\r\n ignoreAttributes: false,\r\n attributeNamePrefix: ''\r\n });\r\n const parsed = parser.parse(xmlContent);\r\n\r\n // get PackageReference node\r\n const project = parsed.Project;\r\n const itemGroups = Array.isArray(project.ItemGroup) ? project.ItemGroup : [project.ItemGroup];\r\n\r\n let isFalconUnitTestProject = false;\r\n\r\n for (const group of itemGroups) {\r\n if(!group) continue;\r\n const refs = group.PackageReference;\r\n if (!refs) continue;\r\n\r\n // PackageReference\r\n const refList = Array.isArray(refs) ? refs : [refs];\r\n\r\n for (const ref of refList) {\r\n if (ref.Include === 'Microsoft.Falcon.CodeAnalyzers') {\r\n isFalconUnitTestProject = true;\r\n console.log('Found Microsoft.Falcon.CodeAnalyzers');\r\n break;\r\n }\r\n }\r\n\r\n if (isFalconUnitTestProject) break;\r\n }\r\n\r\n // if (!isFalconUnitTestProject) {\r\n // console.log('Microsoft.Falcon.CodeAnalyzers not found');\r\n // }\r\n\r\n return isFalconUnitTestProject;\r\n}\r\n\r\nfunction isProjectNameMatchedTestProject(csprojPath: string, projectAssemblyName: string, projectName: string) {\r\n const testProjectName = path.basename(csprojPath, '.csproj').toLowerCase();\r\n const projectNameLower = projectName.toLowerCase();\r\n \r\n // Check if test project name exactly matches: projectName + suffix\r\n const suffixes = ['.tests', '.test', '.unittest', '.unittests', 'tests', 'test'];\r\n const exactMatch = suffixes.some(suffix => testProjectName === projectNameLower + suffix);\r\n \r\n if (exactMatch) {\r\n return true;\r\n }\r\n \r\n // Fallback: check assembly name with exact match\r\n const testProjectAssemblyName = getAssemblyName(csprojPath);\r\n if (testProjectAssemblyName) {\r\n const assemblyNameLower = testProjectAssemblyName.toLowerCase();\r\n const projectAssemblyNameLower = projectAssemblyName.toLowerCase();\r\n return suffixes.some(suffix => assemblyNameLower === projectAssemblyNameLower + suffix);\r\n }\r\n \r\n return false;\r\n}\r\n\r\n/**\r\n * Search for test projects in repository directories\r\n * Walks up from source file directory and collects all test projects that reference the source project\r\n * \r\n * @param csFilePath - Path to the source .cs file\r\n * @param repoRoot - Repository root directory\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @param normalizedProjectPath - Normalized path to source project\r\n * @returns Array of test project paths that reference the source project\r\n */\r\nfunction searchTestProjectsInRepositories(\r\n csFilePath: string,\r\n repoRoot: string,\r\n projectFilePath: string,\r\n normalizedProjectPath: string\r\n): string[] {\r\n let currentDir = path.dirname(csFilePath);\r\n const possibleTestProjects: string[] = [];\r\n const excludedPaths: string[] = [currentDir];\r\n const repoRootParentPath = path.dirname(repoRoot);\r\n \r\n currentDir = path.dirname(currentDir);\r\n while (currentDir !== repoRootParentPath) {\r\n const csprojFiles = findAllCsprojFiles(currentDir, excludedPaths);\r\n \r\n // Filter csproj files by standard test project naming patterns\r\n const testProjectCandidates = csprojFiles.filter(csproj => {\r\n const rawName = path.basename(csproj, '.csproj');\r\n const csprojName = rawName.toLowerCase();\r\n // Standard test naming: ends with .tests, .test, .unittests, .unittest, Tests, or Test\r\n if (\r\n csprojName.endsWith('.tests') || \r\n csprojName.endsWith('.test') || \r\n csprojName.endsWith('.unittests') || \r\n csprojName.endsWith('.unittest') ||\r\n csprojName.endsWith('tests') ||\r\n csprojName.endsWith('test')\r\n ) {\r\n return true;\r\n }\r\n\r\n // Word-level match: any word ends with \"test\" or \"tests\"\r\n const words = extractWordsFromName(rawName);\r\n return words.some(w => w.endsWith('test') || w.endsWith('tests'));\r\n });\r\n \r\n for (const csproj of testProjectCandidates) {\r\n // Check if this csproj references the source project\r\n const projectReferences = getProjectReferencesFromCsproj(csproj);\r\n const referencesSourceProject = checkTestProjectReferencesSourceProject(csproj, normalizedProjectPath, projectReferences);\r\n \r\n if (!referencesSourceProject) {\r\n continue;\r\n }\r\n \r\n const projectName = path.basename(projectFilePath, '.csproj');\r\n const projectAssemblyName = getAssemblyName(projectFilePath);\r\n if (isProjectNameMatchedTestProject(csproj, projectAssemblyName, projectName)) {\r\n return [csproj];\r\n }\r\n \r\n // Collect all test projects that reference the source project\r\n possibleTestProjects.push(csproj);\r\n }\r\n \r\n excludedPaths.push(currentDir);\r\n currentDir = path.dirname(currentDir);\r\n }\r\n \r\n return possibleTestProjects;\r\n}\r\n\r\n/**\r\n * Filter test projects by subfolder matching\r\n * Returns projects sorted by match count, or proceeds to file name matching if all zero\r\n * \r\n * @param possibleTestProjects - List of test project paths\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @returns Filtered projects with scores, or null if needs file name matching\r\n */\r\nfunction filterBySubfolderMatching(\r\n possibleTestProjects: string[],\r\n projectFilePath: string\r\n): Array<{ csproj: string, matchCount: number }> | null {\r\n const sourceProjectDir = path.dirname(projectFilePath);\r\n const sourceSubfolders = getSubfolderNamesRecursive(sourceProjectDir);\r\n\r\n const projectsWithScores = possibleTestProjects.map(csproj => {\r\n const testProjectDir = path.dirname(csproj);\r\n const testSubfolders = getSubfolderNamesRecursive(testProjectDir);\r\n \r\n let matchCount = 0;\r\n testSubfolders.forEach(folderName => {\r\n if (sourceSubfolders.has(folderName)) {\r\n matchCount++;\r\n }\r\n });\r\n \r\n return { csproj, matchCount };\r\n });\r\n\r\n projectsWithScores.sort((a, b) => b.matchCount - a.matchCount);\r\n\r\n const allZero = projectsWithScores.every(p => p.matchCount === 0);\r\n return allZero ? null : projectsWithScores;\r\n}\r\n\r\n/**\r\n * Filter test projects by file name matching with test suffixes\r\n * Returns filtered projects if any matches found\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @returns Filtered projects by file name, or null if no matches\r\n */\r\nfunction filterByFileNameMatching(\r\n projectsWithScores: Array<{ csproj: string, matchCount: number }>,\r\n projectFilePath: string\r\n): Array<{ csproj: string, matchCount: number }> | null {\r\n const sourceProjectDir = path.dirname(projectFilePath);\r\n const sourceFileNames = getFileNamesRecursive(sourceProjectDir);\r\n const testSuffixes = ['.tests', '.test', '.unittests', '.unittest', 'tests', 'test'];\r\n\r\n const filteredProjectsWithScores = projectsWithScores.filter(projectScore => {\r\n const testProjectDir = path.dirname(projectScore.csproj);\r\n const testFileNames = getFileNamesRecursive(testProjectDir);\r\n\r\n for (const sourceFileName of sourceFileNames) {\r\n for (const suffix of testSuffixes) {\r\n const expectedTestFileName = (sourceFileName + suffix).toLowerCase();\r\n if (testFileNames.has(expectedTestFileName)) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n });\r\n\r\n return filteredProjectsWithScores.length > 0 ? filteredProjectsWithScores : null;\r\n}\r\n\r\n/**\r\n * Filter test projects by word-level matching\r\n * Returns top 2 projects with highest word match count\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param projectName - Name of source project\r\n * @returns Top 2 projects by word match count, or empty array if no matches\r\n */\r\nfunction filterByWordLevelMatching(\r\n projectsWithScores: Array<{ csproj: string, matchCount: number }>,\r\n projectName: string\r\n): string[] {\r\n const projectsWithWordScores = projectsWithScores.map(projectScore => {\r\n const testProjectName = path.basename(projectScore.csproj, '.csproj');\r\n const wordMatchCount = calculateWordMatchCount(projectName, testProjectName);\r\n return { ...projectScore, wordMatchCount };\r\n });\r\n\r\n const projectsWithMatches = projectsWithWordScores.filter(p => p.wordMatchCount > 0);\r\n\r\n if (projectsWithMatches.length === 0) {\r\n return [];\r\n }\r\n\r\n projectsWithMatches.sort((a, b) => b.wordMatchCount - a.wordMatchCount);\r\n\r\n const countToReturn = Math.min(2, projectsWithMatches.length);\r\n return projectsWithMatches.slice(0, countToReturn).map(p => p.csproj);\r\n}\r\n\r\n/**\r\n * Select top projects by score percentage or minimum count\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param minCount - Minimum projects to return (default 2)\r\n * @returns Array of selected project paths\r\n */\r\nfunction selectTopProjectsByScore(\r\n projectsWithScores: Array<{ csproj: string, [key: string]: any }>,\r\n minCount: number = 2\r\n): string[] {\r\n const countToReturn = Math.max(minCount, Math.ceil(projectsWithScores.length * 0.3));\r\n return projectsWithScores.slice(0, countToReturn).map(p => p.csproj);\r\n}\r\n\r\n/**\r\n * Find possible test projects for a C# source file\r\n * Uses multi-level matching: folder names -> file names -> word-level matching\r\n * \r\n * @param csFilePath - Path to the source .cs file\r\n * @returns Array of possible test project paths\r\n */\r\nfunction findPossibleTestProjectsFromCsFile(csFilePath: string): string[] {\r\n const repoRoot = getCodeRepoRoot(csFilePath);\r\n const projectFilePath = getSourceFileCsprojFilePath(csFilePath);\r\n const projectName = path.basename(projectFilePath, '.csproj');\r\n const normalizedProjectPath = path.normalize(projectFilePath);\r\n\r\n // Search for test projects in repository\r\n const possibleTestProjects = searchTestProjectsInRepositories(\r\n csFilePath,\r\n repoRoot,\r\n projectFilePath,\r\n normalizedProjectPath\r\n );\r\n\r\n if (possibleTestProjects.length === 0) {\r\n return [];\r\n }\r\n\r\n if (possibleTestProjects.length === 1) {\r\n return possibleTestProjects;\r\n }\r\n\r\n // Try subfolder-level matching\r\n const subfolderMatchResults = filterBySubfolderMatching(possibleTestProjects, projectFilePath);\r\n if (subfolderMatchResults !== null) {\r\n return selectTopProjectsByScore(subfolderMatchResults);\r\n }\r\n\r\n // If subfolder matching is all zero, try file name matching\r\n const projectsWithScores = possibleTestProjects.map(csproj => ({ csproj, matchCount: 0 }));\r\n const fileNameMatchResults = filterByFileNameMatching(projectsWithScores, projectFilePath);\r\n if (fileNameMatchResults !== null) {\r\n return selectTopProjectsByScore(fileNameMatchResults);\r\n }\r\n\r\n // If file name matching fails, try word-level matching\r\n const wordLevelResults = filterByWordLevelMatching(projectsWithScores, projectName);\r\n return wordLevelResults.length > 0 ? wordLevelResults : [];\r\n}\r\n\r\nfunction findPossibleTestFiles(testProjectDir: string, className: string): string[] {\r\n const results: string[] = [];\r\n const stack: string[] = [testProjectDir];\r\n\r\n while (stack.length > 0) {\r\n const currentDir = stack.pop()!;\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n if (entry.name === \"bin\" || entry.name === \"obj\") {\r\n continue;\r\n }\r\n const fullPath = path.join(currentDir, entry.name);\r\n if (entry.isDirectory()) {\r\n stack.push(fullPath);\r\n } else if (entry.isFile() && entry.name.endsWith('.cs') && entry.name.includes(className)) {\r\n results.push(fullPath);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nfunction fileContainsTestAttributes(filePath: string): boolean {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n return TEST_ATTR_REGEX.test(content);\r\n}\r\n\r\n/**\r\n * Check if a test project references a source project.\r\n * \r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @param projectReferences - Project references from the test csproj\r\n * @returns True if test project references the source project, false otherwise\r\n */\r\nfunction checkTestProjectReferencesSourceProject(\r\n testCsprojPath: string,\r\n sourceCsprojPath: string,\r\n projectReferences: string[]\r\n): boolean {\r\n const normalizedSourceCsprojPath = path.normalize(sourceCsprojPath).toLowerCase();\r\n return projectReferences.some(ref => {\r\n const resolvedRefPath = path.normalize(path.resolve(path.dirname(testCsprojPath), ref)).toLowerCase();\r\n return resolvedRefPath === normalizedSourceCsprojPath;\r\n });\r\n}\r\n\r\nfunction getProjectReferencesFromCsproj(csprojPath: string): string[] {\r\n const projectReferences: string[] = [];\r\n try {\r\n const xmlContent = fs.readFileSync(csprojPath, 'utf-8');\r\n const parser = new XMLParser({\r\n ignoreAttributes: false,\r\n attributeNamePrefix: ''\r\n });\r\n const projectData = parser.parse(xmlContent);\r\n \r\n const project = projectData.Project;\r\n const itemGroups = Array.isArray(project.ItemGroup) ? project.ItemGroup : [project.ItemGroup];\r\n \r\n for (const group of itemGroups) {\r\n if (!group) continue;\r\n const projectRefs = group.ProjectReference;\r\n if (!projectRefs) continue;\r\n\r\n const refList = Array.isArray(projectRefs) ? projectRefs : [projectRefs];\r\n for (const ref of refList) {\r\n if (ref.Include) {\r\n projectReferences.push(ref.Include);\r\n }\r\n }\r\n }\r\n } catch (err) {\r\n console.error(`Failed to parse csproj: ${csprojPath}`, err);\r\n }\r\n return projectReferences;\r\n}\r\n\r\n/**\r\n * Calculate matching score between test file path and source file path based on directory structure.\r\n * Returns two scores: continuous matching folders from end, and total matching folders.\r\n * \r\n * @param testRelativePath - Relative path of test file from test project root\r\n * @param sourceRelativePath - Relative path of source file from source project root\r\n * @returns Object with 'continuous' (right-to-left consecutive matches) and 'total' (all matches)\r\n */\r\nfunction calculateMatchingScore(testRelativePath: string, sourceRelativePath: string): { continuous: number, total: number } {\r\n // Extract directory paths (remove file names)\r\n const testDir = path.dirname(testRelativePath);\r\n const sourceDir = path.dirname(sourceRelativePath);\r\n \r\n // If both files are in root directory (no subdirectories), give highest priority\r\n if ((testDir === '.' || testDir === '') && (sourceDir === '.' || sourceDir === '')) {\r\n return { continuous: 1000, total: 1000 };\r\n }\r\n \r\n // Split paths into folder arrays (case-insensitive)\r\n const testFolders = testDir === '.' || testDir === '' ? [] : testDir.split(path.sep).map(f => f.toLowerCase());\r\n const sourceFolders = sourceDir === '.' || sourceDir === '' ? [] : sourceDir.split(path.sep).map(f => f.toLowerCase());\r\n \r\n // 1. Calculate continuous matching folders from end (right to left)\r\n let continuous = 0;\r\n const minLength = Math.min(testFolders.length, sourceFolders.length);\r\n \r\n for (let i = 1; i <= minLength; i++) {\r\n if (testFolders[testFolders.length - i] === sourceFolders[sourceFolders.length - i]) {\r\n continuous++;\r\n } else {\r\n // Stop at first mismatch\r\n break;\r\n }\r\n }\r\n \r\n // 2. Calculate total matching folders (not required to be continuous)\r\n const sourceSet = new Set(sourceFolders);\r\n const total = testFolders.filter(f => sourceSet.has(f)).length;\r\n \r\n return { continuous, total };\r\n}\r\n\r\nfunction isTestFileForSourceFile(testFilePath: string, sourceCodePath: string): boolean {\r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n const testFileName = path.basename(testFilePath, '.cs');\r\n \r\n // First check: test file name should match common test patterns\r\n // Patterns: SourceFile + (Unit)? + (.)? + (Test|Tests)\r\n // Examples: SourceFileTests, SourceFileTest, SourceFile.Tests, SourceFile.Test, SourceFileUnitTests, SourceFileUnit.Tests\r\n const testPattern = getTestFileNamePattern(sourceFileName);\r\n const matchesPattern = testPattern.test(testFileName);\r\n if (!matchesPattern) {\r\n return false;\r\n }\r\n \r\n try {\r\n // Read both files content\r\n const testContent = fs.readFileSync(testFilePath, 'utf-8');\r\n const sourceContent = fs.readFileSync(sourceCodePath, 'utf-8');\r\n \r\n // First check: Extract namespace from source file and verify test file references it\r\n const sourceNamespaceMatch = sourceContent.match(/namespace\\s+([\\w.]+)/);\r\n if (!sourceNamespaceMatch || !sourceNamespaceMatch[1]) {\r\n // No namespace found in source file, fall back to name-based matching\r\n return true;\r\n }\r\n \r\n const sourceNamespace = sourceNamespaceMatch[1];\r\n // Check if test file has using statement for source namespace\r\n const usingRegex = new RegExp(`using\\\\s+${sourceNamespace.replace(/\\./g, '\\\\.')};`);\r\n if (!usingRegex.test(testContent)) {\r\n // Test file doesn't reference source namespace\r\n return false;\r\n }\r\n \r\n // Second check: Extract the main type name from source file (public or internal)\r\n // Supports: class, interface, struct, record (but not nested private/protected types)\r\n // Priority: public > internal; match first public, fallback to first internal\r\n // Handles modifiers: sealed, abstract, static, partial\r\n const publicTypeMatch = sourceContent.match(new RegExp(`\\\\bpublic\\\\s+${MODIFIER_PATTERN}(?:class|interface|struct|record)\\\\s+(\\\\w+)`));\r\n const internalTypeMatch = sourceContent.match(new RegExp(`\\\\binternal\\\\s+${MODIFIER_PATTERN}(?:class|interface|struct|record)\\\\s+(\\\\w+)`));\r\n \r\n const sourceTypeMatch = publicTypeMatch || internalTypeMatch;\r\n if (!sourceTypeMatch || !sourceTypeMatch[1]) {\r\n // No public or internal type found - this file might be a utility/helper file\r\n // without testable classes, so it shouldn't have a test file\r\n return false;\r\n }\r\n \r\n const sourceTypeName = sourceTypeMatch[1];\r\n // Check if test file references the source type name or its interface\r\n // If source is an interface (direct interface definition), only match itself\r\n // If source is a class/struct/record, also match interface (ITypeName)\r\n const isSourceInterface = new RegExp(`\\\\b(?:public|internal)\\\\s+${MODIFIER_PATTERN}interface\\\\s+(?:\\\\w+)`).test(sourceContent);\r\n let sourceCodeTypeReferenceRegex: RegExp;\r\n if (isSourceInterface) {\r\n // Source is an interface, match only itself\r\n sourceCodeTypeReferenceRegex = new RegExp(`\\\\b${sourceTypeName}\\\\b`, 'g');\r\n } else {\r\n // Source is a class/struct/record, match both TypeName and ITypeName\r\n sourceCodeTypeReferenceRegex = new RegExp(`\\\\b(I)?${sourceTypeName}\\\\b`, 'g');\r\n }\r\n \r\n if (sourceCodeTypeReferenceRegex.test(testContent)) {\r\n return true;\r\n }\r\n \r\n // Namespace matches but class name not found in test file\r\n return false;\r\n \r\n } catch (err) {\r\n console.error(`Failed to read file content for matching: ${err}`);\r\n // Strict mode: if we can't verify the content, treat as non-matching\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Find an existing test file from sibling source files in the same or parent directories.\r\n * This helps determine the best location for a new test file by looking at where\r\n * existing test files are located for nearby source files.\r\n * \r\n * @param sourceCodePath - Path to the source file\r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @returns Object with siblingTestFilePath and sourceRelativeDepth if found, otherwise null\r\n */\r\nfunction findSiblingTestFile(\r\n sourceCodePath: string,\r\n testCsprojPath: string,\r\n sourceCsprojPath: string\r\n): { siblingTestFilePath: string, sourceRelativeDepth: number } | null {\r\n const sourceProjectDir = path.dirname(sourceCsprojPath);\r\n let currentDir = path.dirname(sourceCodePath);\r\n let depth = 0;\r\n \r\n // Search from current directory up to source project root\r\n while (currentDir.toLowerCase().startsWith(sourceProjectDir.toLowerCase()) && currentDir.length >= sourceProjectDir.length) {\r\n try {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n const csFiles = entries\r\n .filter(e => e.isFile() && e.name.endsWith('.cs') && path.join(currentDir, e.name) !== sourceCodePath)\r\n .map(e => path.join(currentDir, e.name));\r\n \r\n for (const csFile of csFiles) {\r\n // Try to find test file for this sibling source file\r\n const result = findMatchingTestFileInProject(testCsprojPath, csFile, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n return { siblingTestFilePath: result.testFilePath, sourceRelativeDepth: depth };\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n \r\n // Move to parent directory\r\n const parentDir = path.dirname(currentDir);\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n currentDir = parentDir;\r\n depth++;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/**\r\n * Determine the best test file path for a source file.\r\n * This function only calculates the path, it does not create any directories.\r\n * \r\n * @param sourceCodePath - Path to the source file\r\n * @param testCsprojPath - Path to the test project's csproj file (optional)\r\n * @returns Object with testFilePath, testProjectPath, and testFileExist flag\r\n */\r\nexport function determineTestFilePath(sourceCodePath: string, testCsprojPath?: string): { testFilePath: string | null, testProjectPath: string | null, testFileExist?: boolean } {\r\n let testProjectPath = testCsprojPath;\r\n if (!testProjectPath) {\r\n console.error(`No test project found for ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n \r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n const testFileName = `${sourceFileName}Tests.cs`;\r\n const sourceFileProjectPath = getSourceFileProjectDir(sourceCodePath);\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n \r\n // Try to find sibling test file to determine the best location\r\n const siblingResult = findSiblingTestFile(sourceCodePath, testProjectPath, sourceCsprojPath);\r\n \r\n let testFilePath: string;\r\n if (siblingResult) {\r\n // Found sibling test file, calculate new test file path based on it\r\n const siblingTestDir = path.dirname(siblingResult.siblingTestFilePath);\r\n const sourceFileDir = path.dirname(sourceCodePath);\r\n \r\n if (siblingResult.sourceRelativeDepth === 0) {\r\n // Sibling is in the same directory, put test file in the same test directory\r\n testFilePath = path.join(siblingTestDir, testFileName);\r\n } else {\r\n // Sibling is in a parent directory, calculate the relative path from sibling source to current source\r\n let relativeParts: string[] = [];\r\n let tempDir = sourceFileDir;\r\n \r\n for (let i = 0; i < siblingResult.sourceRelativeDepth; i++) {\r\n relativeParts.unshift(path.basename(tempDir));\r\n tempDir = path.dirname(tempDir);\r\n }\r\n \r\n // The relative path from the found sibling source dir to our source file\r\n const relativePath = relativeParts.join(path.sep);\r\n testFilePath = path.join(siblingTestDir, relativePath, testFileName);\r\n }\r\n } else {\r\n // No sibling test file found, use original logic\r\n const sourceFileDir = path.dirname(sourceCodePath);\r\n const testFileRelativePath = sourceFileDir.replace(sourceFileProjectPath, \"\");\r\n const testProjecDir = path.dirname(testProjectPath);\r\n testFilePath = path.join(testProjecDir, testFileRelativePath, testFileName);\r\n }\r\n \r\n // Check if the test file already exists\r\n const testFileExist = fs.existsSync(testFilePath);\r\n if (testFileExist) {\r\n console.log(`Test file already exists at ${testFilePath}`);\r\n }\r\n \r\n return { testFilePath, testProjectPath, testFileExist };\r\n}\r\n\r\n/**\r\n * Search for matching test file in a specific test project.\r\n * Uses directory structure matching and file content analysis to find the best match.\r\n * \r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCodePath - Path to the source file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @returns Object with testFilePath and testProjectPath if found, otherwise both null\r\n */\r\nfunction findMatchingTestFileInProject(\r\n testCsprojPath: string,\r\n sourceCodePath: string,\r\n sourceCsprojPath: string\r\n): { testFilePath: string | null, testProjectPath: string | null } {\r\n const testProjectDir = path.dirname(testCsprojPath);\r\n \r\n // Get source file's csproj directory\r\n const sourceCsprojDir = path.dirname(sourceCsprojPath);\r\n // Calculate relative path of source file from its csproj directory\r\n const sourceRelativePath = path.relative(sourceCsprojDir, sourceCodePath);\r\n \r\n // Get source file name for filtering\r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n \r\n // Find .cs files containing source file name (optimization to reduce file count)\r\n const allTestFiles = findPossibleTestFiles(testProjectDir, sourceFileName);\r\n \r\n // Filter by file name pattern first to reduce unnecessary file reads\r\n const testPattern = getTestFileNamePattern(sourceFileName);\r\n \r\n // Create list of candidates with their matching scores\r\n const candidatesWithScores = allTestFiles\r\n .filter(file => {\r\n const testFileName = path.basename(file, '.cs');\r\n return testPattern.test(testFileName);\r\n })\r\n .map(file => {\r\n const testRelativePath = path.relative(testProjectDir, file);\r\n const score = calculateMatchingScore(testRelativePath, sourceRelativePath);\r\n return {\r\n filePath: file,\r\n relativePath: testRelativePath,\r\n score: score\r\n };\r\n })\r\n // Sort by continuous match first, then by total match\r\n .sort((a, b) => {\r\n if (b.score.continuous !== a.score.continuous) {\r\n return b.score.continuous - a.score.continuous;\r\n }\r\n return b.score.total - a.score.total;\r\n });\r\n \r\n for (const candidate of candidatesWithScores) {\r\n if (isTestFileForSourceFile(candidate.filePath, sourceCodePath)) {\r\n return { testFilePath: candidate.filePath, testProjectPath: testCsprojPath };\r\n }\r\n }\r\n \r\n return { testFilePath: null, testProjectPath: null };\r\n}\r\n\r\nfunction getTestFileFromChangedFiles(sourceCodePath: string, changedTestFiles?: string[]): { testFilePath: string | null, testProjectPath: string | null } {\r\n if (!changedTestFiles || changedTestFiles.length === 0) {\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n\r\n console.log(`Searching test file from ${changedTestFiles.length} changed test files for source: ${sourceCodePath}`);\r\n\r\n // Get the csproj of the source code\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n if (!sourceCsprojPath) {\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n\r\n // Cache to store project references from csproj to avoid re-parsing\r\n const csprojCache = new Map<string, string[]>();\r\n // Store test projects that reference the source project\r\n const referencingTestProjects = new Set<string>();\r\n\r\n for (const testFilePath of changedTestFiles) {\r\n if (!fs.existsSync(testFilePath)) {\r\n continue;\r\n }\r\n\r\n // Get the csproj of the test file\r\n const testCsprojPath = getSourceFileCsprojFilePath(testFilePath);\r\n if (!testCsprojPath) {\r\n continue;\r\n }\r\n\r\n // Check cache first\r\n let projectReferences = csprojCache.get(testCsprojPath);\r\n if (!projectReferences) {\r\n projectReferences = getProjectReferencesFromCsproj(testCsprojPath);\r\n csprojCache.set(testCsprojPath, projectReferences);\r\n }\r\n\r\n // Check if test project references the source project\r\n const normalizedSourceCsprojPath = path.normalize(sourceCsprojPath);\r\n if (checkTestProjectReferencesSourceProject(testCsprojPath, normalizedSourceCsprojPath, projectReferences)) {\r\n referencingTestProjects.add(testCsprojPath);\r\n // Check if this test file is for the source file\r\n if (isTestFileForSourceFile(testFilePath, sourceCodePath)) {\r\n return { testFilePath, testProjectPath: testCsprojPath };\r\n }\r\n }\r\n }\r\n\r\n // Fallback: search all test files in projects that reference the source project\r\n for (const testCsprojPath of referencingTestProjects) {\r\n const result = findMatchingTestFileInProject(testCsprojPath, sourceCodePath, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n return result;\r\n }\r\n }\r\n\r\n return { testFilePath: null, testProjectPath: null };\r\n}\r\n\r\nexport function getOrCreatTestFile(sourceCodePath: string, testFilePath: string, changedTestFiles?: string[]) {\r\n let finalTestFilePath = testFilePath;\r\n let finalTestProjectPath;\r\n let testFileExist = !!testFilePath && fs.existsSync(testFilePath);\r\n \r\n // If testFilePath is provided, get its project path and return directly\r\n if (testFilePath && testFilePath.trim() !== '') {\r\n finalTestProjectPath = getSourceFileCsprojFilePath(testFilePath);\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n }\r\n \r\n // if outputPath param is not provided, try to find an existing test file\r\n // if no existing test file found, create a new one in test project\r\n console.log(' Output path is missing. outputPath:', testFilePath, ', start looking for existing test project');\r\n\r\n // Try to find test file from changed files first\r\n let resultFromChangedFiles = getTestFileFromChangedFiles(sourceCodePath, changedTestFiles);\r\n if (resultFromChangedFiles.testFilePath) {\r\n return { testFilePath: resultFromChangedFiles.testFilePath, testProjectPath: resultFromChangedFiles.testProjectPath, testFileExist: true };\r\n }\r\n\r\n // Fallback: try to find existing test file\r\n const possibleCSProjPaths = findPossibleTestProjectsFromCsFile(sourceCodePath);\r\n if (!possibleCSProjPaths || possibleCSProjPaths.length === 0) {\r\n console.error(` No test project found for source code: ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n\r\n // Get the source csproj path for matching\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n if (!sourceCsprojPath) {\r\n console.error(` Cannot find source csproj for: ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n\r\n // Try to find existing test file in each possible test project\r\n for (const testCsprojPath of possibleCSProjPaths) {\r\n const result = findMatchingTestFileInProject(testCsprojPath, sourceCodePath, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n testFileExist = true;\r\n finalTestFilePath = result.testFilePath;\r\n finalTestProjectPath = result.testProjectPath;\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n }\r\n }\r\n\r\n // No existing test file found, determine test file path (may find existing)\r\n const result = determineTestFilePath(sourceCodePath, possibleCSProjPaths[0]);\r\n if (!result.testFilePath || !result.testProjectPath) {\r\n console.error(`Failed to determine test file path for ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n finalTestFilePath = result.testFilePath;\r\n finalTestProjectPath = result.testProjectPath;\r\n testFileExist = result.testFileExist ?? false;\r\n \r\n // Create directory if test file doesn't exist\r\n if (!testFileExist) {\r\n getOrCreateDir(path.dirname(finalTestFilePath));\r\n }\r\n\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n\r\n}\r\n\r\n// // Verify test file paths for all projects\r\n// function verifyTestFilePaths(): void {\r\n// const baseFolder = 'Q:\\\\src\\\\Microsoft.News.OneService';\r\n// const outputFile = 'q:\\\\verifyTestFilePaths_results.txt';\r\n// const results: string[] = [];\r\n\r\n// try {\r\n// // Recursively find all non test csproj files \r\n// const getAllCsprojFiles = (dir: string): string[] => {\r\n// const csprojFiles: string[] = [];\r\n// try {\r\n// const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n// for (const entry of entries) {\r\n// const fullPath = path.join(dir, entry.name);\r\n// if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n// csprojFiles.push(...getAllCsprojFiles(fullPath));\r\n// } else if (entry.isFile() && entry.name.endsWith('.csproj')) {\r\n// // Filter by test project naming patterns\r\n// const rawName = path.basename(fullPath, '.csproj');\r\n// const words = rawName\r\n// .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n// .split(/[^a-zA-Z0-9]+/)\r\n// .filter(Boolean)\r\n// .map(w => w.toLowerCase());\r\n \r\n// if (words.every(w => !w.endsWith('test') && !w.endsWith('tests'))) {\r\n// csprojFiles.push(fullPath);\r\n// }\r\n// }\r\n// }\r\n// } catch (err) {\r\n// // Skip inaccessible directories\r\n// }\r\n// return csprojFiles;\r\n// };\r\n\r\n// // Get first .cs file in a directory (recursive search)\r\n// const getFirstCsFile = (dir: string): string | null => {\r\n// try {\r\n// const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n// // First pass: look for .cs files in current directory\r\n// for (const entry of entries) {\r\n// if (entry.isFile() && entry.name.endsWith('.cs')) {\r\n// return path.join(dir, entry.name);\r\n// }\r\n// }\r\n// // Second pass: recurse into subdirectories\r\n// for (const entry of entries) {\r\n// if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n// const fullPath = path.join(dir, entry.name);\r\n// const result = getFirstCsFile(fullPath);\r\n// if (result) {\r\n// return result;\r\n// }\r\n// }\r\n// }\r\n// } catch (err) {\r\n// // Skip if directory can't be read\r\n// }\r\n// return null;\r\n// };\r\n\r\n// // Find all csproj files\r\n// const csprojFiles = getAllCsprojFiles(baseFolder);\r\n\r\n// // Process each csproj\r\n// for (const csprojPath of csprojFiles) {\r\n// const csprojDir = path.dirname(csprojPath);\r\n// const csFile = getFirstCsFile(csprojDir);\r\n\r\n// if (csFile) {\r\n// const result = getOrCreatTestFile(csFile, undefined);\r\n// const testFilePath = result.testFilePath || 'NOT_FOUND';\r\n// const testProjectPath = result.testProjectPath || 'NOT_FOUND';\r\n// results.push(`${csprojPath}\\t${csFile}\\t${testFilePath}\\t${testProjectPath}\\t${result.testFileExist}`);\r\n// console.log(`Processed: ${csprojPath}`);\r\n// }\r\n// }\r\n\r\n// // Write results to file\r\n// fs.writeFileSync(outputFile, results.join('\\n'), 'utf-8');\r\n// console.log(`Results written to ${outputFile}`);\r\n// } catch (err) {\r\n// console.error(`Error during verification: ${err}`);\r\n// }\r\n// }\r\n\r\n// // Uncomment to run verification\r\n// verifyTestFilePaths();\r\n\r\n// getOrCreatTestFile(\"Q:\\\\src\\\\Microsoft.News.OneService\\\\Libraries\\\\Tests\\\\MockStrategies\\\\MockDataException.cs\", undefined);\r\n\r\n\r\n// Example usage\r\n// const csFilePath = \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\LocationDetection\\\\AudienceResponseParser.cs\";\r\n// const csFilePath = \"D:\\\\code\\\\msnews-experiences\\\\experiences\\\\weather-right-rail\\\\src\\\\WeatherRightRail.connector.ts\";\r\n// const testProjectPath = \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Tests\\\\SharedSegments.Tests.csproj\";\r\n// if (!csFilePath) {\r\n// console.error('Usage: ts-node findTestFile.ts path/to/your/file.cs');\r\n// process.exit(1);\r\n// }\r\n\r\n// const start = Date.now();\r\n// const testFilePath = getExistingTestFile(csFilePath);\r\n// console.log(`Test file for ${csFilePath}:`, testFilePath ?? 'No test file found');\r\n// console.log(`Search completed in ${(Date.now() - start) / 1000} seconds`);\r\n// createXapTestFile(csFilePath);\r\n\r\n// const repoDir = getCodeRepoRoot(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\LocationDetection\\\\AudienceResponseParser.cs\");\r\n// console.log(`Code repository root directory: ${repoDir}`);\r\n\r\n// const result = getExistingTestFile(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Eplant\\\\EplantConfigManager.cs\");\r\n// console.log(`Test file path: ${result.testFilePath}`);\r\n// console.log(`Test project path: ${result.testProjectPath}`);\r\n\r\n\r\n// falcon test project\r\n// const isFlaconUt = isFalconUnitTestProject(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\tests\\\\UnitTests\\\\Microsoft.Falcon.WeatherUserInterest.UnitTests.csproj\");\r\n// console.log(`Is Falcon Unit Test Project: ${isFlaconUt}`);\r\n// const testProject = findTestProjectFromCsFile(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\src\\\\Service\\\\Microsoft.Falcon.WeatherUserInterest.csproj\");\r\n// console.log(`Test project path: ${testProject}`);\r\n// const testFilePath = getOrCreatTestFile(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\src\\\\Service\\\\Components\\\\IUserInterestTable.cs\", undefined, false);\r\n// console.log(`Test file path: ${testFilePath.testFilePath}`);\r\n\r\n// ads projects\r\n// const testProjectPath = findTestProjectFromCsFile(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UCMDynamics.AppointmentPlugin\\\\AppointmentOperation.cs\");\r\n// console.log(`Test project path: ${testProjectPath}`);\r\n// const isValid = isGeneralTestProject(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UcmDynamics.AppointmentPlugin\\\\UcmDynamics.AppointmentPlugin.csproj\");\r\n// // const isValid = isGeneralTestProject(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UcmDynamics.AppointmentPlugin.Tests\\\\UcmDynamics.AppointmentPlugin.Tests.csproj\");\r\n// console.log(`Is General Test Project: ${isValid}`);\r\n\r\n// const testProjectPath = findTestProjectFromCsFile(\"D:\\\\code\\\\AIUnitTestExample\\\\src\\\\ToListinator.Analyzers\\\\ToListCountAnalyzer.cs\");\r\n// console.log(`Test project path: ${testProjectPath}`);"]}
1
+ {"version":3,"file":"getTestFile.js","sourceRoot":"","sources":["../../src/utils/getTestFile.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nimport { getAssemblyName, getCodeRepoRoot, getSourceFileCsprojFilePath, getSourceFileProjectDir } from './getCodeStructurePath';\r\nimport { getOrCreateDir } from './getOrCreateDir';\r\n\r\nimport { XMLParser } from 'fast-xml-parser';\r\n\r\nconst TEST_NAME_REGEX = /(Test|Tests)/i;\r\nconst TEST_ATTR_REGEX = /\\[(Fact|Theory|TestClass|TestMethod|Test)\\]/;\r\n\r\n/**\r\n * Check if a file path is a test file based on common naming conventions.\r\n * Checks if the file name (without .cs extension) ends with test, tests, unittest, or unittests.\r\n */\r\nexport function isTestFile(filepath: string): boolean {\r\n const fileName = path.basename(filepath).toLowerCase();\r\n const fileNameWithoutExt = fileName.replace(/\\.cs$/, '');\r\n \r\n return fileNameWithoutExt.endsWith('test') || \r\n fileNameWithoutExt.endsWith('tests') ||\r\n fileNameWithoutExt.endsWith('unittest') ||\r\n fileNameWithoutExt.endsWith('unittests');\r\n}\r\n\r\n// Modifier pattern for C# type declarations (sealed, abstract, static, partial)\r\nconst MODIFIER_PATTERN = `(?:sealed|abstract|static|partial)?\\\\s*`;\r\n\r\n// Helper function to create test file name pattern\r\nfunction getTestFileNamePattern(sourceFileName: string): RegExp {\r\n return new RegExp(`^${sourceFileName}(Unit)?(\\\\.)?(Test|Tests)$`);\r\n}\r\n\r\n/**\r\n * Extract words from a name string (e.g., project name, file name)\r\n * Splits by camelCase and special characters, returns lowercase words\r\n * \r\n * @param name - The name string to extract words from\r\n * @returns Array of lowercase words\r\n */\r\nfunction extractWordsFromName(name: string): string[] {\r\n return name\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .split(/[^a-zA-Z0-9]+/)\r\n .filter(Boolean)\r\n .map(w => w.toLowerCase());\r\n}\r\n\r\n/**\r\n * Calculate word-level matching score between two names\r\n * Returns the count of matching words\r\n * \r\n * @param name1 - First name to compare\r\n * @param name2 - Second name to compare\r\n * @returns Number of matching words\r\n */\r\nfunction calculateWordMatchCount(name1: string, name2: string): number {\r\n const words1 = extractWordsFromName(name1);\r\n const words2 = extractWordsFromName(name2);\r\n \r\n const words1Set = new Set(words1);\r\n return words2.filter(w => words1Set.has(w)).length;\r\n}\r\n\r\n/**\r\n * Get all subfolder names under a directory (recursive)\r\n * Skips: bin, obj, .vs directories\r\n * \r\n * @param dirPath - Path to directory\r\n * @returns Set of lowercase folder names\r\n */\r\nfunction getSubfolderNamesRecursive(dirPath: string): Set<string> {\r\n const subfolders = new Set<string>();\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n subfolders.add(entry.name.toLowerCase());\r\n // Recursively get subfolders\r\n const subPath = path.join(dirPath, entry.name);\r\n const deepSubfolders = getSubfolderNamesRecursive(subPath);\r\n deepSubfolders.forEach(f => subfolders.add(f));\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n return subfolders;\r\n}\r\n\r\n/**\r\n * Get all .cs file names under a directory (recursive)\r\n * Skips: bin, obj, .vs directories\r\n * \r\n * @param dirPath - Path to directory\r\n * @returns Set of lowercase file names (without .cs extension)\r\n */\r\nfunction getFileNamesRecursive(dirPath: string): Set<string> {\r\n const fileNames = new Set<string>();\r\n try {\r\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.name === 'bin' || entry.name === 'obj' || entry.name === '.vs') {\r\n continue;\r\n }\r\n const fullPath = path.join(dirPath, entry.name);\r\n if (entry.isDirectory()) {\r\n // Recursively get file names from subdirectories\r\n const subFileNames = getFileNamesRecursive(fullPath);\r\n subFileNames.forEach(f => fileNames.add(f));\r\n } else if (entry.isFile() && entry.name.endsWith('.cs')) {\r\n // Add file name without .cs extension\r\n fileNames.add(entry.name.slice(0, -3).toLowerCase());\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n return fileNames;\r\n}\r\n\r\nfunction findAllCsprojFiles(dir: string, excludedPaths: string[]): string[] {\r\n const results: string[] = [];\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n if (entry.name === \".vs\" || excludedPaths.includes(fullPath)) {\r\n continue; // Skip excluded paths\r\n }\r\n\r\n if (entry.isDirectory()) {\r\n results.push(...findAllCsprojFiles(fullPath, excludedPaths));\r\n } else if (entry.isFile() && entry.name.endsWith('.csproj')) {\r\n results.push(fullPath);\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nfunction isXapTestProject(csprojPath: string): boolean {\r\n try {\r\n const content = fs.readFileSync(csprojPath, 'utf-8');\r\n const parser = new XMLParser({ ignoreAttributes: false, ignoreDeclaration: true });\r\n const json = parser.parse(content);\r\n const project = json.Project;\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.XapProjectType === 'TestProject') {\r\n return true;\r\n }\r\n }\r\n } catch (err: any) {\r\n console.error(`Failed to parse ${csprojPath}: ${err.message}`);\r\n }\r\n return false;\r\n}\r\n\r\nfunction isGeneralTestProject(csprojPath: string): boolean {\r\n try {\r\n const content = fs.readFileSync(csprojPath, 'utf-8');\r\n\r\n // 1. package reference (test framework)\r\n const referencesTestFramework = /<PackageReference\\s+Include=\"(xunit|nunit|MSTest\\.TestFramework|Microsoft\\.NET\\.Test\\.Sdk)\"/i.test(content);\r\n\r\n // 2. file name *.Tests.csproj\r\n const fileNameHasTests = (/\\.Tests\\.csproj$/i.test(path.basename(csprojPath))) || (/\\.Test\\.csproj$/i.test(path.basename(csprojPath)));\r\n\r\n // 3. path contains Tests\r\n const pathHasTests = /[\\\\/](Tests?|UnitTests?|IntegrationTests?)[\\\\/]/i.test(csprojPath);\r\n\r\n // 4. Project SDK is test type (optional)\r\n const sdkIsTestSdk = /<Project\\s+Sdk=\"Microsoft\\.NET\\.Test\\.Sdk\"/i.test(content);\r\n\r\n // 组合判断\r\n return referencesTestFramework || sdkIsTestSdk || fileNameHasTests || pathHasTests;\r\n } catch (err) {\r\n console.error(`can't read csproj file: ${csprojPath}`);\r\n return false;\r\n }\r\n}\r\n\r\nfunction isFalconUnitTestProject(csprojPath: string): boolean {\r\n const xmlContent = fs.readFileSync(csprojPath, 'utf-8');\r\n\r\n const parser = new XMLParser({\r\n ignoreAttributes: false,\r\n attributeNamePrefix: ''\r\n });\r\n const parsed = parser.parse(xmlContent);\r\n\r\n // get PackageReference node\r\n const project = parsed.Project;\r\n const itemGroups = Array.isArray(project.ItemGroup) ? project.ItemGroup : [project.ItemGroup];\r\n\r\n let isFalconUnitTestProject = false;\r\n\r\n for (const group of itemGroups) {\r\n if(!group) continue;\r\n const refs = group.PackageReference;\r\n if (!refs) continue;\r\n\r\n // PackageReference\r\n const refList = Array.isArray(refs) ? refs : [refs];\r\n\r\n for (const ref of refList) {\r\n if (ref.Include === 'Microsoft.Falcon.CodeAnalyzers') {\r\n isFalconUnitTestProject = true;\r\n console.log('Found Microsoft.Falcon.CodeAnalyzers');\r\n break;\r\n }\r\n }\r\n\r\n if (isFalconUnitTestProject) break;\r\n }\r\n\r\n // if (!isFalconUnitTestProject) {\r\n // console.log('Microsoft.Falcon.CodeAnalyzers not found');\r\n // }\r\n\r\n return isFalconUnitTestProject;\r\n}\r\n\r\nfunction isProjectNameMatchedTestProject(csprojPath: string, projectAssemblyName: string, projectName: string) {\r\n const testProjectName = path.basename(csprojPath, '.csproj').toLowerCase();\r\n const projectNameLower = projectName.toLowerCase();\r\n \r\n // Check if test project name exactly matches: projectName + suffix\r\n const suffixes = ['.tests', '.test', '.unittest', '.unittests', 'tests', 'test'];\r\n const exactMatch = suffixes.some(suffix => testProjectName === projectNameLower + suffix);\r\n \r\n if (exactMatch) {\r\n return true;\r\n }\r\n \r\n // Fallback: check assembly name with exact match\r\n const testProjectAssemblyName = getAssemblyName(csprojPath);\r\n if (testProjectAssemblyName) {\r\n const assemblyNameLower = testProjectAssemblyName.toLowerCase();\r\n const projectAssemblyNameLower = projectAssemblyName.toLowerCase();\r\n return suffixes.some(suffix => assemblyNameLower === projectAssemblyNameLower + suffix);\r\n }\r\n \r\n return false;\r\n}\r\n\r\n/**\r\n * Search for test projects in repository directories\r\n * Walks up from source file directory and collects all test projects that reference the source project\r\n * \r\n * @param csFilePath - Path to the source .cs file\r\n * @param repoRoot - Repository root directory\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @param normalizedProjectPath - Normalized path to source project\r\n * @returns Array of test project paths that reference the source project\r\n */\r\nfunction searchTestProjectsInRepositories(\r\n csFilePath: string,\r\n repoRoot: string,\r\n projectFilePath: string,\r\n normalizedProjectPath: string\r\n): string[] {\r\n let currentDir = path.dirname(csFilePath);\r\n const possibleTestProjects: string[] = [];\r\n const excludedPaths: string[] = [currentDir];\r\n const repoRootParentPath = path.dirname(repoRoot);\r\n \r\n currentDir = path.dirname(currentDir);\r\n while (currentDir !== repoRootParentPath) {\r\n const csprojFiles = findAllCsprojFiles(currentDir, excludedPaths);\r\n \r\n // Filter csproj files by standard test project naming patterns\r\n const testProjectCandidates = csprojFiles.filter(csproj => {\r\n const rawName = path.basename(csproj, '.csproj');\r\n const csprojName = rawName.toLowerCase();\r\n // Standard test naming: ends with .tests, .test, .unittests, .unittest, Tests, or Test\r\n if (\r\n csprojName.endsWith('.tests') || \r\n csprojName.endsWith('.test') || \r\n csprojName.endsWith('.unittests') || \r\n csprojName.endsWith('.unittest') ||\r\n csprojName.endsWith('tests') ||\r\n csprojName.endsWith('test')\r\n ) {\r\n return true;\r\n }\r\n\r\n // Word-level match: any word ends with \"test\" or \"tests\"\r\n const words = extractWordsFromName(rawName);\r\n return words.some(w => w.endsWith('test') || w.endsWith('tests'));\r\n });\r\n \r\n for (const csproj of testProjectCandidates) {\r\n // Check if this csproj references the source project\r\n const projectReferences = getProjectReferencesFromCsproj(csproj);\r\n const referencesSourceProject = checkTestProjectReferencesSourceProject(csproj, normalizedProjectPath, projectReferences);\r\n \r\n if (!referencesSourceProject) {\r\n continue;\r\n }\r\n \r\n const projectName = path.basename(projectFilePath, '.csproj');\r\n const projectAssemblyName = getAssemblyName(projectFilePath);\r\n if (isProjectNameMatchedTestProject(csproj, projectAssemblyName, projectName)) {\r\n return [csproj];\r\n }\r\n \r\n // Collect all test projects that reference the source project\r\n possibleTestProjects.push(csproj);\r\n }\r\n \r\n excludedPaths.push(currentDir);\r\n currentDir = path.dirname(currentDir);\r\n }\r\n \r\n return possibleTestProjects;\r\n}\r\n\r\n/**\r\n * Filter test projects by subfolder matching\r\n * Returns projects sorted by match count, or proceeds to file name matching if all zero\r\n * \r\n * @param possibleTestProjects - List of test project paths\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @returns Filtered projects with scores, or null if needs file name matching\r\n */\r\nfunction filterBySubfolderMatching(\r\n possibleTestProjects: string[],\r\n projectFilePath: string\r\n): Array<{ csproj: string, matchCount: number }> | null {\r\n const sourceProjectDir = path.dirname(projectFilePath);\r\n const sourceSubfolders = getSubfolderNamesRecursive(sourceProjectDir);\r\n\r\n const projectsWithScores = possibleTestProjects.map(csproj => {\r\n const testProjectDir = path.dirname(csproj);\r\n const testSubfolders = getSubfolderNamesRecursive(testProjectDir);\r\n \r\n let matchCount = 0;\r\n testSubfolders.forEach(folderName => {\r\n if (sourceSubfolders.has(folderName)) {\r\n matchCount++;\r\n }\r\n });\r\n \r\n return { csproj, matchCount };\r\n });\r\n\r\n projectsWithScores.sort((a, b) => b.matchCount - a.matchCount);\r\n\r\n const allZero = projectsWithScores.every(p => p.matchCount === 0);\r\n return allZero ? null : projectsWithScores;\r\n}\r\n\r\n/**\r\n * Filter test projects by file name matching with test suffixes\r\n * Returns filtered projects if any matches found\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param projectFilePath - Path to source project's .csproj\r\n * @returns Filtered projects by file name, or null if no matches\r\n */\r\nfunction filterByFileNameMatching(\r\n projectsWithScores: Array<{ csproj: string, matchCount: number }>,\r\n projectFilePath: string\r\n): Array<{ csproj: string, matchCount: number }> | null {\r\n const sourceProjectDir = path.dirname(projectFilePath);\r\n const sourceFileNames = getFileNamesRecursive(sourceProjectDir);\r\n const testSuffixes = ['.tests', '.test', '.unittests', '.unittest', 'tests', 'test'];\r\n\r\n const filteredProjectsWithScores = projectsWithScores.filter(projectScore => {\r\n const testProjectDir = path.dirname(projectScore.csproj);\r\n const testFileNames = getFileNamesRecursive(testProjectDir);\r\n\r\n for (const sourceFileName of sourceFileNames) {\r\n for (const suffix of testSuffixes) {\r\n const expectedTestFileName = (sourceFileName + suffix).toLowerCase();\r\n if (testFileNames.has(expectedTestFileName)) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n });\r\n\r\n return filteredProjectsWithScores.length > 0 ? filteredProjectsWithScores : null;\r\n}\r\n\r\n/**\r\n * Filter test projects by word-level matching\r\n * Returns top 2 projects with highest word match count\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param projectName - Name of source project\r\n * @returns Top 2 projects by word match count, or empty array if no matches\r\n */\r\nfunction filterByWordLevelMatching(\r\n projectsWithScores: Array<{ csproj: string, matchCount: number }>,\r\n projectName: string\r\n): string[] {\r\n const projectsWithWordScores = projectsWithScores.map(projectScore => {\r\n const testProjectName = path.basename(projectScore.csproj, '.csproj');\r\n const wordMatchCount = calculateWordMatchCount(projectName, testProjectName);\r\n return { ...projectScore, wordMatchCount };\r\n });\r\n\r\n const projectsWithMatches = projectsWithWordScores.filter(p => p.wordMatchCount > 0);\r\n\r\n if (projectsWithMatches.length === 0) {\r\n return [];\r\n }\r\n\r\n projectsWithMatches.sort((a, b) => b.wordMatchCount - a.wordMatchCount);\r\n\r\n const countToReturn = Math.min(2, projectsWithMatches.length);\r\n return projectsWithMatches.slice(0, countToReturn).map(p => p.csproj);\r\n}\r\n\r\n/**\r\n * Select top projects by score percentage or minimum count\r\n * \r\n * @param projectsWithScores - Projects with scores\r\n * @param minCount - Minimum projects to return (default 2)\r\n * @returns Array of selected project paths\r\n */\r\nfunction selectTopProjectsByScore(\r\n projectsWithScores: Array<{ csproj: string, [key: string]: any }>,\r\n minCount: number = 2\r\n): string[] {\r\n const countToReturn = Math.max(minCount, Math.ceil(projectsWithScores.length * 0.3));\r\n return projectsWithScores.slice(0, countToReturn).map(p => p.csproj);\r\n}\r\n\r\n/**\r\n * Find possible test projects for a C# source file\r\n * Uses multi-level matching: folder names -> file names -> word-level matching\r\n * \r\n * @param csFilePath - Path to the source .cs file\r\n * @returns Array of possible test project paths\r\n */\r\nfunction findPossibleTestProjectsFromCsFile(csFilePath: string): string[] {\r\n const repoRoot = getCodeRepoRoot(csFilePath);\r\n const projectFilePath = getSourceFileCsprojFilePath(csFilePath);\r\n const projectName = path.basename(projectFilePath, '.csproj');\r\n const normalizedProjectPath = path.normalize(projectFilePath);\r\n\r\n // Search for test projects in repository\r\n const possibleTestProjects = searchTestProjectsInRepositories(\r\n csFilePath,\r\n repoRoot,\r\n projectFilePath,\r\n normalizedProjectPath\r\n );\r\n\r\n if (possibleTestProjects.length === 0) {\r\n return [];\r\n }\r\n\r\n if (possibleTestProjects.length === 1) {\r\n return possibleTestProjects;\r\n }\r\n\r\n // Try subfolder-level matching\r\n const subfolderMatchResults = filterBySubfolderMatching(possibleTestProjects, projectFilePath);\r\n if (subfolderMatchResults !== null) {\r\n return selectTopProjectsByScore(subfolderMatchResults);\r\n }\r\n\r\n // If subfolder matching is all zero, try file name matching\r\n const projectsWithScores = possibleTestProjects.map(csproj => ({ csproj, matchCount: 0 }));\r\n const fileNameMatchResults = filterByFileNameMatching(projectsWithScores, projectFilePath);\r\n if (fileNameMatchResults !== null) {\r\n return selectTopProjectsByScore(fileNameMatchResults);\r\n }\r\n\r\n // If file name matching fails, try word-level matching\r\n const wordLevelResults = filterByWordLevelMatching(projectsWithScores, projectName);\r\n return wordLevelResults.length > 0 ? wordLevelResults : [];\r\n}\r\n\r\nfunction findPossibleTestFiles(testProjectDir: string, className: string): string[] {\r\n const results: string[] = [];\r\n const stack: string[] = [testProjectDir];\r\n\r\n while (stack.length > 0) {\r\n const currentDir = stack.pop()!;\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n if (entry.name === \"bin\" || entry.name === \"obj\") {\r\n continue;\r\n }\r\n const fullPath = path.join(currentDir, entry.name);\r\n if (entry.isDirectory()) {\r\n stack.push(fullPath);\r\n } else if (entry.isFile() && entry.name.endsWith('.cs') && entry.name.includes(className)) {\r\n results.push(fullPath);\r\n }\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\nfunction fileContainsTestAttributes(filePath: string): boolean {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n return TEST_ATTR_REGEX.test(content);\r\n}\r\n\r\n/**\r\n * Check if a test project references a source project.\r\n * \r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @param projectReferences - Project references from the test csproj\r\n * @returns True if test project references the source project, false otherwise\r\n */\r\nfunction checkTestProjectReferencesSourceProject(\r\n testCsprojPath: string,\r\n sourceCsprojPath: string,\r\n projectReferences: string[]\r\n): boolean {\r\n const normalizedSourceCsprojPath = path.normalize(sourceCsprojPath).toLowerCase();\r\n return projectReferences.some(ref => {\r\n const resolvedRefPath = path.normalize(path.resolve(path.dirname(testCsprojPath), ref)).toLowerCase();\r\n return resolvedRefPath === normalizedSourceCsprojPath;\r\n });\r\n}\r\n\r\nfunction getProjectReferencesFromCsproj(csprojPath: string): string[] {\r\n const projectReferences: string[] = [];\r\n try {\r\n const xmlContent = fs.readFileSync(csprojPath, 'utf-8');\r\n const parser = new XMLParser({\r\n ignoreAttributes: false,\r\n attributeNamePrefix: ''\r\n });\r\n const projectData = parser.parse(xmlContent);\r\n \r\n const project = projectData.Project;\r\n const itemGroups = Array.isArray(project.ItemGroup) ? project.ItemGroup : [project.ItemGroup];\r\n \r\n for (const group of itemGroups) {\r\n if (!group) continue;\r\n const projectRefs = group.ProjectReference;\r\n if (!projectRefs) continue;\r\n\r\n const refList = Array.isArray(projectRefs) ? projectRefs : [projectRefs];\r\n for (const ref of refList) {\r\n if (ref.Include) {\r\n projectReferences.push(ref.Include);\r\n }\r\n }\r\n }\r\n } catch (err) {\r\n console.error(`Failed to parse csproj: ${csprojPath}`, err);\r\n }\r\n return projectReferences;\r\n}\r\n\r\n/**\r\n * Calculate matching score between test file path and source file path based on directory structure.\r\n * Returns two scores: continuous matching folders from end, and total matching folders.\r\n * \r\n * @param testRelativePath - Relative path of test file from test project root\r\n * @param sourceRelativePath - Relative path of source file from source project root\r\n * @returns Object with 'continuous' (right-to-left consecutive matches) and 'total' (all matches)\r\n */\r\nfunction calculateMatchingScore(testRelativePath: string, sourceRelativePath: string): { continuous: number, total: number } {\r\n // Extract directory paths (remove file names)\r\n const testDir = path.dirname(testRelativePath);\r\n const sourceDir = path.dirname(sourceRelativePath);\r\n \r\n // If both files are in root directory (no subdirectories), give highest priority\r\n if ((testDir === '.' || testDir === '') && (sourceDir === '.' || sourceDir === '')) {\r\n return { continuous: 1000, total: 1000 };\r\n }\r\n \r\n // Split paths into folder arrays (case-insensitive)\r\n const testFolders = testDir === '.' || testDir === '' ? [] : testDir.split(path.sep).map(f => f.toLowerCase());\r\n const sourceFolders = sourceDir === '.' || sourceDir === '' ? [] : sourceDir.split(path.sep).map(f => f.toLowerCase());\r\n \r\n // 1. Calculate continuous matching folders from end (right to left)\r\n let continuous = 0;\r\n const minLength = Math.min(testFolders.length, sourceFolders.length);\r\n \r\n for (let i = 1; i <= minLength; i++) {\r\n if (testFolders[testFolders.length - i] === sourceFolders[sourceFolders.length - i]) {\r\n continuous++;\r\n } else {\r\n // Stop at first mismatch\r\n break;\r\n }\r\n }\r\n \r\n // 2. Calculate total matching folders (not required to be continuous)\r\n const sourceSet = new Set(sourceFolders);\r\n const total = testFolders.filter(f => sourceSet.has(f)).length;\r\n \r\n return { continuous, total };\r\n}\r\n\r\nfunction isTestFileForSourceFile(testFilePath: string, sourceCodePath: string): boolean {\r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n const testFileName = path.basename(testFilePath, '.cs');\r\n \r\n // First check: test file name should match common test patterns\r\n // Patterns: SourceFile + (Unit)? + (.)? + (Test|Tests)\r\n // Examples: SourceFileTests, SourceFileTest, SourceFile.Tests, SourceFile.Test, SourceFileUnitTests, SourceFileUnit.Tests\r\n const testPattern = getTestFileNamePattern(sourceFileName);\r\n const matchesPattern = testPattern.test(testFileName);\r\n if (!matchesPattern) {\r\n return false;\r\n }\r\n \r\n try {\r\n // Read both files content\r\n const testContent = fs.readFileSync(testFilePath, 'utf-8');\r\n const sourceContent = fs.readFileSync(sourceCodePath, 'utf-8');\r\n \r\n // First check: Extract namespace from source file and verify test file references it\r\n const sourceNamespaceMatch = sourceContent.match(/namespace\\s+([\\w.]+)/);\r\n if (!sourceNamespaceMatch || !sourceNamespaceMatch[1]) {\r\n // No namespace found in source file, fall back to name-based matching\r\n return true;\r\n }\r\n \r\n const sourceNamespace = sourceNamespaceMatch[1];\r\n // Check if test file has using statement for source namespace\r\n const usingRegex = new RegExp(`using\\\\s+${sourceNamespace.replace(/\\./g, '\\\\.')};`);\r\n if (!usingRegex.test(testContent)) {\r\n // Test file doesn't reference source namespace\r\n return false;\r\n }\r\n \r\n // Second check: Extract the main type name from source file (public or internal)\r\n // Supports: class, interface, struct, record (but not nested private/protected types)\r\n // Priority: public > internal; match first public, fallback to first internal\r\n // Handles modifiers: sealed, abstract, static, partial\r\n const publicTypeMatch = sourceContent.match(new RegExp(`\\\\bpublic\\\\s+${MODIFIER_PATTERN}(?:class|interface|struct|record)\\\\s+(\\\\w+)`));\r\n const internalTypeMatch = sourceContent.match(new RegExp(`\\\\binternal\\\\s+${MODIFIER_PATTERN}(?:class|interface|struct|record)\\\\s+(\\\\w+)`));\r\n \r\n const sourceTypeMatch = publicTypeMatch || internalTypeMatch;\r\n if (!sourceTypeMatch || !sourceTypeMatch[1]) {\r\n // No public or internal type found - this file might be a utility/helper file\r\n // without testable classes, so it shouldn't have a test file\r\n return false;\r\n }\r\n \r\n const sourceTypeName = sourceTypeMatch[1];\r\n // Check if test file references the source type name or its interface\r\n // If source is an interface (direct interface definition), only match itself\r\n // If source is a class/struct/record, also match interface (ITypeName)\r\n const isSourceInterface = new RegExp(`\\\\b(?:public|internal)\\\\s+${MODIFIER_PATTERN}interface\\\\s+(?:\\\\w+)`).test(sourceContent);\r\n let sourceCodeTypeReferenceRegex: RegExp;\r\n if (isSourceInterface) {\r\n // Source is an interface, match only itself\r\n sourceCodeTypeReferenceRegex = new RegExp(`\\\\b${sourceTypeName}\\\\b`, 'g');\r\n } else {\r\n // Source is a class/struct/record, match both TypeName and ITypeName\r\n sourceCodeTypeReferenceRegex = new RegExp(`\\\\b(I)?${sourceTypeName}\\\\b`, 'g');\r\n }\r\n \r\n if (sourceCodeTypeReferenceRegex.test(testContent)) {\r\n return true;\r\n }\r\n \r\n // Namespace matches but class name not found in test file\r\n return false;\r\n \r\n } catch (err) {\r\n console.error(`Failed to read file content for matching: ${err}`);\r\n // Strict mode: if we can't verify the content, treat as non-matching\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Find an existing test file from sibling source files in the same or parent directories.\r\n * This helps determine the best location for a new test file by looking at where\r\n * existing test files are located for nearby source files.\r\n * \r\n * @param sourceCodePath - Path to the source file\r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @returns Object with siblingTestFilePath and sourceRelativeDepth if found, otherwise null\r\n */\r\nfunction findSiblingTestFile(\r\n sourceCodePath: string,\r\n testCsprojPath: string,\r\n sourceCsprojPath: string\r\n): { siblingTestFilePath: string, sourceRelativeDepth: number } | null {\r\n const sourceProjectDir = path.dirname(sourceCsprojPath);\r\n let currentDir = path.dirname(sourceCodePath);\r\n let depth = 0;\r\n \r\n // Search from current directory up to source project root\r\n while (currentDir.toLowerCase().startsWith(sourceProjectDir.toLowerCase()) && currentDir.length >= sourceProjectDir.length) {\r\n try {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n const csFiles = entries\r\n .filter(e => e.isFile() && e.name.endsWith('.cs') && path.join(currentDir, e.name) !== sourceCodePath)\r\n .map(e => path.join(currentDir, e.name));\r\n \r\n for (const csFile of csFiles) {\r\n // Try to find test file for this sibling source file\r\n const result = findMatchingTestFileInProject(testCsprojPath, csFile, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n return { siblingTestFilePath: result.testFilePath, sourceRelativeDepth: depth };\r\n }\r\n }\r\n } catch (err) {\r\n // Ignore errors for inaccessible directories\r\n }\r\n \r\n // Move to parent directory\r\n const parentDir = path.dirname(currentDir);\r\n if (parentDir === currentDir) {\r\n break;\r\n }\r\n currentDir = parentDir;\r\n depth++;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/**\r\n * Determine the best test file path for a source file.\r\n * This function only calculates the path, it does not create any directories.\r\n * \r\n * @param sourceCodePath - Path to the source file\r\n * @param testCsprojPath - Path to the test project's csproj file (optional)\r\n * @returns Object with testFilePath, testProjectPath, and testFileExist flag\r\n */\r\nexport function determineTestFilePath(sourceCodePath: string, testCsprojPath?: string): { testFilePath: string | null, testProjectPath: string | null, testFileExist?: boolean } {\r\n let testProjectPath = testCsprojPath;\r\n if (!testProjectPath) {\r\n console.error(`No test project found for ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n \r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n const testFileName = `${sourceFileName}Tests.cs`;\r\n const sourceFileProjectPath = getSourceFileProjectDir(sourceCodePath);\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n \r\n // Try to find sibling test file to determine the best location\r\n const siblingResult = findSiblingTestFile(sourceCodePath, testProjectPath, sourceCsprojPath);\r\n \r\n let testFilePath: string;\r\n if (siblingResult) {\r\n // Found sibling test file, calculate new test file path based on it\r\n const siblingTestDir = path.dirname(siblingResult.siblingTestFilePath);\r\n const sourceFileDir = path.dirname(sourceCodePath);\r\n \r\n if (siblingResult.sourceRelativeDepth === 0) {\r\n // Sibling is in the same directory, put test file in the same test directory\r\n testFilePath = path.join(siblingTestDir, testFileName);\r\n } else {\r\n // Sibling is in a parent directory, calculate the relative path from sibling source to current source\r\n let relativeParts: string[] = [];\r\n let tempDir = sourceFileDir;\r\n \r\n for (let i = 0; i < siblingResult.sourceRelativeDepth; i++) {\r\n relativeParts.unshift(path.basename(tempDir));\r\n tempDir = path.dirname(tempDir);\r\n }\r\n \r\n // The relative path from the found sibling source dir to our source file\r\n const relativePath = relativeParts.join(path.sep);\r\n testFilePath = path.join(siblingTestDir, relativePath, testFileName);\r\n }\r\n } else {\r\n // No sibling test file found, use original logic\r\n const sourceFileDir = path.dirname(sourceCodePath);\r\n const testFileRelativePath = sourceFileDir.replace(sourceFileProjectPath, \"\");\r\n const testProjecDir = path.dirname(testProjectPath);\r\n testFilePath = path.join(testProjecDir, testFileRelativePath, testFileName);\r\n }\r\n \r\n // Check if the test file already exists\r\n const testFileExist = fs.existsSync(testFilePath);\r\n if (testFileExist) {\r\n console.log(`Test file already exists at ${testFilePath}`);\r\n }\r\n \r\n return { testFilePath, testProjectPath, testFileExist };\r\n}\r\n\r\n/**\r\n * Search for matching test file in a specific test project.\r\n * Uses directory structure matching and file content analysis to find the best match.\r\n * \r\n * @param testCsprojPath - Path to the test project's csproj file\r\n * @param sourceCodePath - Path to the source file\r\n * @param sourceCsprojPath - Path to the source project's csproj file\r\n * @returns Object with testFilePath and testProjectPath if found, otherwise both null\r\n */\r\nfunction findMatchingTestFileInProject(\r\n testCsprojPath: string,\r\n sourceCodePath: string,\r\n sourceCsprojPath: string\r\n): { testFilePath: string | null, testProjectPath: string | null } {\r\n const testProjectDir = path.dirname(testCsprojPath);\r\n \r\n // Get source file's csproj directory\r\n const sourceCsprojDir = path.dirname(sourceCsprojPath);\r\n // Calculate relative path of source file from its csproj directory\r\n const sourceRelativePath = path.relative(sourceCsprojDir, sourceCodePath);\r\n \r\n // Get source file name for filtering\r\n const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n \r\n // Find .cs files containing source file name (optimization to reduce file count)\r\n const allTestFiles = findPossibleTestFiles(testProjectDir, sourceFileName);\r\n \r\n // Filter by file name pattern first to reduce unnecessary file reads\r\n const testPattern = getTestFileNamePattern(sourceFileName);\r\n \r\n // Create list of candidates with their matching scores\r\n const candidatesWithScores = allTestFiles\r\n .filter(file => {\r\n const testFileName = path.basename(file, '.cs');\r\n return testPattern.test(testFileName);\r\n })\r\n .map(file => {\r\n const testRelativePath = path.relative(testProjectDir, file);\r\n const score = calculateMatchingScore(testRelativePath, sourceRelativePath);\r\n return {\r\n filePath: file,\r\n relativePath: testRelativePath,\r\n score: score\r\n };\r\n })\r\n // Sort by continuous match first, then by total match\r\n .sort((a, b) => {\r\n if (b.score.continuous !== a.score.continuous) {\r\n return b.score.continuous - a.score.continuous;\r\n }\r\n return b.score.total - a.score.total;\r\n });\r\n \r\n for (const candidate of candidatesWithScores) {\r\n if (isTestFileForSourceFile(candidate.filePath, sourceCodePath)) {\r\n return { testFilePath: candidate.filePath, testProjectPath: testCsprojPath };\r\n }\r\n }\r\n \r\n return { testFilePath: null, testProjectPath: null };\r\n}\r\n\r\nfunction getTestFileFromChangedFiles(sourceCodePath: string, changedTestFiles?: string[]): { testFilePath: string | null, testProjectPath: string | null } {\r\n if (!changedTestFiles || changedTestFiles.length === 0) {\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n\r\n console.log(`Searching test file from ${changedTestFiles.length} changed test files for source: ${sourceCodePath}`);\r\n\r\n // Get the csproj of the source code\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n if (!sourceCsprojPath) {\r\n return { testFilePath: null, testProjectPath: null };\r\n }\r\n\r\n // Cache to store project references from csproj to avoid re-parsing\r\n const csprojCache = new Map<string, string[]>();\r\n // Store test projects that reference the source project\r\n const referencingTestProjects = new Set<string>();\r\n\r\n for (const testFilePath of changedTestFiles) {\r\n if (!fs.existsSync(testFilePath)) {\r\n continue;\r\n }\r\n\r\n // Get the csproj of the test file\r\n const testCsprojPath = getSourceFileCsprojFilePath(testFilePath);\r\n if (!testCsprojPath) {\r\n continue;\r\n }\r\n\r\n // Check cache first\r\n let projectReferences = csprojCache.get(testCsprojPath);\r\n if (!projectReferences) {\r\n projectReferences = getProjectReferencesFromCsproj(testCsprojPath);\r\n csprojCache.set(testCsprojPath, projectReferences);\r\n }\r\n\r\n // Check if test project references the source project\r\n const normalizedSourceCsprojPath = path.normalize(sourceCsprojPath);\r\n if (checkTestProjectReferencesSourceProject(testCsprojPath, normalizedSourceCsprojPath, projectReferences)) {\r\n referencingTestProjects.add(testCsprojPath);\r\n // Check if this test file is for the source file\r\n if (isTestFileForSourceFile(testFilePath, sourceCodePath)) {\r\n return { testFilePath, testProjectPath: testCsprojPath };\r\n }\r\n }\r\n }\r\n\r\n // Fallback: search all test files in projects that reference the source project\r\n for (const testCsprojPath of referencingTestProjects) {\r\n const result = findMatchingTestFileInProject(testCsprojPath, sourceCodePath, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n return result;\r\n }\r\n }\r\n\r\n return { testFilePath: null, testProjectPath: null };\r\n}\r\n\r\nexport function getOrCreatTestFile(sourceCodePath: string, testFilePath: string, changedTestFiles?: string[]) {\r\n let finalTestFilePath = testFilePath;\r\n let finalTestProjectPath;\r\n let testFileExist = !!testFilePath && fs.existsSync(testFilePath);\r\n \r\n // If testFilePath is provided, get its project path and return directly\r\n if (testFilePath && testFilePath.trim() !== '') {\r\n finalTestProjectPath = getSourceFileCsprojFilePath(testFilePath);\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n }\r\n \r\n // if outputPath param is not provided, try to find an existing test file\r\n // if no existing test file found, create a new one in test project\r\n console.log(' Output path is missing, start looking for existing test project');\r\n\r\n // Try to find test file from changed files first\r\n let resultFromChangedFiles = getTestFileFromChangedFiles(sourceCodePath, changedTestFiles);\r\n if (resultFromChangedFiles.testFilePath) {\r\n return { testFilePath: resultFromChangedFiles.testFilePath, testProjectPath: resultFromChangedFiles.testProjectPath, testFileExist: true };\r\n }\r\n\r\n // Fallback: try to find existing test file\r\n const possibleCSProjPaths = findPossibleTestProjectsFromCsFile(sourceCodePath);\r\n if (!possibleCSProjPaths || possibleCSProjPaths.length === 0) {\r\n console.error(` No test project found for source code: ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n\r\n // Get the source csproj path for matching\r\n const sourceCsprojPath = getSourceFileCsprojFilePath(sourceCodePath);\r\n if (!sourceCsprojPath) {\r\n console.error(` Cannot find source csproj for: ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n\r\n // Try to find existing test file in each possible test project\r\n for (const testCsprojPath of possibleCSProjPaths) {\r\n const result = findMatchingTestFileInProject(testCsprojPath, sourceCodePath, sourceCsprojPath);\r\n if (result.testFilePath) {\r\n testFileExist = true;\r\n finalTestFilePath = result.testFilePath;\r\n finalTestProjectPath = result.testProjectPath;\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n }\r\n }\r\n\r\n // No existing test file found, determine test file path (may find existing)\r\n const result = determineTestFilePath(sourceCodePath, possibleCSProjPaths[0]);\r\n if (!result.testFilePath || !result.testProjectPath) {\r\n console.error(`Failed to determine test file path for ${sourceCodePath}`);\r\n return { testFilePath: null, testProjectPath: null, testFileExist: false };\r\n }\r\n finalTestFilePath = result.testFilePath;\r\n finalTestProjectPath = result.testProjectPath;\r\n testFileExist = result.testFileExist ?? false;\r\n \r\n // Create directory if test file doesn't exist\r\n if (!testFileExist) {\r\n getOrCreateDir(path.dirname(finalTestFilePath));\r\n }\r\n\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n\r\n}\r\n\r\n// // Verify test file paths for all projects\r\n// function verifyTestFilePaths(): void {\r\n// const baseFolder = 'Q:\\\\src\\\\Microsoft.News.OneService';\r\n// const outputFile = 'q:\\\\verifyTestFilePaths_results.txt';\r\n// const results: string[] = [];\r\n\r\n// try {\r\n// // Recursively find all non test csproj files \r\n// const getAllCsprojFiles = (dir: string): string[] => {\r\n// const csprojFiles: string[] = [];\r\n// try {\r\n// const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n// for (const entry of entries) {\r\n// const fullPath = path.join(dir, entry.name);\r\n// if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n// csprojFiles.push(...getAllCsprojFiles(fullPath));\r\n// } else if (entry.isFile() && entry.name.endsWith('.csproj')) {\r\n// // Filter by test project naming patterns\r\n// const rawName = path.basename(fullPath, '.csproj');\r\n// const words = rawName\r\n// .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n// .split(/[^a-zA-Z0-9]+/)\r\n// .filter(Boolean)\r\n// .map(w => w.toLowerCase());\r\n \r\n// if (words.every(w => !w.endsWith('test') && !w.endsWith('tests'))) {\r\n// csprojFiles.push(fullPath);\r\n// }\r\n// }\r\n// }\r\n// } catch (err) {\r\n// // Skip inaccessible directories\r\n// }\r\n// return csprojFiles;\r\n// };\r\n\r\n// // Get first .cs file in a directory (recursive search)\r\n// const getFirstCsFile = (dir: string): string | null => {\r\n// try {\r\n// const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n// // First pass: look for .cs files in current directory\r\n// for (const entry of entries) {\r\n// if (entry.isFile() && entry.name.endsWith('.cs')) {\r\n// return path.join(dir, entry.name);\r\n// }\r\n// }\r\n// // Second pass: recurse into subdirectories\r\n// for (const entry of entries) {\r\n// if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.vs') {\r\n// const fullPath = path.join(dir, entry.name);\r\n// const result = getFirstCsFile(fullPath);\r\n// if (result) {\r\n// return result;\r\n// }\r\n// }\r\n// }\r\n// } catch (err) {\r\n// // Skip if directory can't be read\r\n// }\r\n// return null;\r\n// };\r\n\r\n// // Find all csproj files\r\n// const csprojFiles = getAllCsprojFiles(baseFolder);\r\n\r\n// // Process each csproj\r\n// for (const csprojPath of csprojFiles) {\r\n// const csprojDir = path.dirname(csprojPath);\r\n// const csFile = getFirstCsFile(csprojDir);\r\n\r\n// if (csFile) {\r\n// const result = getOrCreatTestFile(csFile, undefined);\r\n// const testFilePath = result.testFilePath || 'NOT_FOUND';\r\n// const testProjectPath = result.testProjectPath || 'NOT_FOUND';\r\n// results.push(`${csprojPath}\\t${csFile}\\t${testFilePath}\\t${testProjectPath}\\t${result.testFileExist}`);\r\n// console.log(`Processed: ${csprojPath}`);\r\n// }\r\n// }\r\n\r\n// // Write results to file\r\n// fs.writeFileSync(outputFile, results.join('\\n'), 'utf-8');\r\n// console.log(`Results written to ${outputFile}`);\r\n// } catch (err) {\r\n// console.error(`Error during verification: ${err}`);\r\n// }\r\n// }\r\n\r\n// // Uncomment to run verification\r\n// verifyTestFilePaths();\r\n\r\n// getOrCreatTestFile(\"Q:\\\\src\\\\Microsoft.News.OneService\\\\Libraries\\\\Tests\\\\MockStrategies\\\\MockDataException.cs\", undefined);\r\n\r\n\r\n// Example usage\r\n// const csFilePath = \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\LocationDetection\\\\AudienceResponseParser.cs\";\r\n// const csFilePath = \"D:\\\\code\\\\msnews-experiences\\\\experiences\\\\weather-right-rail\\\\src\\\\WeatherRightRail.connector.ts\";\r\n// const testProjectPath = \"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Tests\\\\SharedSegments.Tests.csproj\";\r\n// if (!csFilePath) {\r\n// console.error('Usage: ts-node findTestFile.ts path/to/your/file.cs');\r\n// process.exit(1);\r\n// }\r\n\r\n// const start = Date.now();\r\n// const testFilePath = getExistingTestFile(csFilePath);\r\n// console.log(`Test file for ${csFilePath}:`, testFilePath ?? 'No test file found');\r\n// console.log(`Search completed in ${(Date.now() - start) / 1000} seconds`);\r\n// createXapTestFile(csFilePath);\r\n\r\n// const repoDir = getCodeRepoRoot(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\LocationDetection\\\\AudienceResponseParser.cs\");\r\n// console.log(`Code repository root directory: ${repoDir}`);\r\n\r\n// const result = getExistingTestFile(\"D:\\\\code\\\\CS.Service.Fundamental\\\\SharedSegments\\\\SharedSegments\\\\SharedSegments.Plugins\\\\Workflows\\\\Eplant\\\\EplantConfigManager.cs\");\r\n// console.log(`Test file path: ${result.testFilePath}`);\r\n// console.log(`Test project path: ${result.testProjectPath}`);\r\n\r\n\r\n// falcon test project\r\n// const isFlaconUt = isFalconUnitTestProject(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\tests\\\\UnitTests\\\\Microsoft.Falcon.WeatherUserInterest.UnitTests.csproj\");\r\n// console.log(`Is Falcon Unit Test Project: ${isFlaconUt}`);\r\n// const testProject = findTestProjectFromCsFile(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\src\\\\Service\\\\Microsoft.Falcon.WeatherUserInterest.csproj\");\r\n// console.log(`Test project path: ${testProject}`);\r\n// const testFilePath = getOrCreatTestFile(\"D:\\\\code\\\\WeatherNotification\\\\services\\\\WeatherUserInterest\\\\src\\\\Service\\\\Components\\\\IUserInterestTable.cs\", undefined, false);\r\n// console.log(`Test file path: ${testFilePath.testFilePath}`);\r\n\r\n// ads projects\r\n// const testProjectPath = findTestProjectFromCsFile(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UCMDynamics.AppointmentPlugin\\\\AppointmentOperation.cs\");\r\n// console.log(`Test project path: ${testProjectPath}`);\r\n// const isValid = isGeneralTestProject(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UcmDynamics.AppointmentPlugin\\\\UcmDynamics.AppointmentPlugin.csproj\");\r\n// // const isValid = isGeneralTestProject(\"D:\\\\code\\\\UCMDynamics\\\\private\\\\DynamicCode\\\\Plugin\\\\UcmDynamics.AppointmentPlugin.Tests\\\\UcmDynamics.AppointmentPlugin.Tests.csproj\");\r\n// console.log(`Is General Test Project: ${isValid}`);\r\n\r\n// const testProjectPath = findTestProjectFromCsFile(\"D:\\\\code\\\\AIUnitTestExample\\\\src\\\\ToListinator.Analyzers\\\\ToListCountAnalyzer.cs\");\r\n// console.log(`Test project path: ${testProjectPath}`);"]}