@ai-dev-tools/csharp-copilot-core 0.0.37 → 0.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/gen/autoFix.d.ts +1 -1
- package/out/gen/autoFix.js +8 -3
- package/out/gen/autoFix.js.map +1 -1
- package/out/gen/ensureValidLLMResponse.d.ts +1 -1
- package/out/gen/ensureValidLLMResponse.js +6 -2
- package/out/gen/ensureValidLLMResponse.js.map +1 -1
- package/out/gen/postGen/postGenMoreUTAutofixProcess.d.ts +17 -0
- package/out/gen/postGen/postGenMoreUTAutofixProcess.js +475 -0
- package/out/gen/postGen/postGenMoreUTAutofixProcess.js.map +1 -0
- package/out/gen/postGen/postGenMoreUTProcess.d.ts +41 -0
- package/out/gen/postGen/postGenMoreUTProcess.js +219 -5
- package/out/gen/postGen/postGenMoreUTProcess.js.map +1 -1
- package/out/llm/prompt/moreUT/generateMoreUtAutoFix.liquid +1 -0
- package/out/utils/getTestFile.js +1 -1
- package/out/utils/getTestFile.js.map +1 -1
- package/out/utils/moreUTAutoFixUtil.d.ts +7 -0
- package/out/utils/moreUTAutoFixUtil.js +51 -0
- package/out/utils/moreUTAutoFixUtil.js.map +1 -0
- package/out/utils/removeFailedTestMethods.d.ts +12 -0
- package/out/utils/removeFailedTestMethods.js +18 -16
- package/out/utils/removeFailedTestMethods.js.map +1 -1
- package/out/utils/spawnExec.js +4 -1
- package/out/utils/spawnExec.js.map +1 -1
- package/out/utils/writeGenCode.d.ts +5 -0
- package/out/utils/writeGenCode.js +15 -0
- package/out/utils/writeGenCode.js.map +1 -1
- package/package.json +1 -1
|
@@ -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}`);"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract test method names that contain errors from build or test results.
|
|
3
|
+
*
|
|
4
|
+
* - Build failure: uses error line numbers to find the enclosing test method in the code.
|
|
5
|
+
* - Test failure: directly reads failed test names from the test result.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractErrorTestMethodNames(testCode: string, isBuildFailure: boolean, buildResult?: any, testResult?: any): string[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractErrorTestMethodNames = extractErrorTestMethodNames;
|
|
4
|
+
const removeFailedTestMethods_1 = require("./removeFailedTestMethods");
|
|
5
|
+
/**
|
|
6
|
+
* Extract test method names that contain errors from build or test results.
|
|
7
|
+
*
|
|
8
|
+
* - Build failure: uses error line numbers to find the enclosing test method in the code.
|
|
9
|
+
* - Test failure: directly reads failed test names from the test result.
|
|
10
|
+
*/
|
|
11
|
+
function extractErrorTestMethodNames(testCode, isBuildFailure, buildResult, testResult) {
|
|
12
|
+
const methodNames = new Set();
|
|
13
|
+
if (isBuildFailure && buildResult) {
|
|
14
|
+
// Build errors: find test method by error line number
|
|
15
|
+
const errors = Array.isArray(buildResult) ? buildResult : (buildResult.errors || []);
|
|
16
|
+
const lines = testCode?.split('\n') || [];
|
|
17
|
+
for (const err of errors) {
|
|
18
|
+
const errorLine = err.line;
|
|
19
|
+
if (!errorLine)
|
|
20
|
+
continue;
|
|
21
|
+
const range = (0, removeFailedTestMethods_1.findTestMethodRangeByBrace)(lines, errorLine - 1); // 0-based
|
|
22
|
+
if (range) {
|
|
23
|
+
// Find method name within the range
|
|
24
|
+
for (let i = range.start; i <= range.end; i++) {
|
|
25
|
+
const trimmed = lines[i].trim();
|
|
26
|
+
if (!trimmed.startsWith('[') && trimmed !== '' && /\b\w+\s*\(/.test(trimmed)) {
|
|
27
|
+
const name = (0, removeFailedTestMethods_1.extractMethodName)(trimmed);
|
|
28
|
+
if (name) {
|
|
29
|
+
methodNames.add(name);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (!isBuildFailure && testResult?.failedTests) {
|
|
38
|
+
// Test errors: directly use failed test names
|
|
39
|
+
for (const failed of testResult.failedTests) {
|
|
40
|
+
if (failed.name) {
|
|
41
|
+
methodNames.add(failed.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const result = Array.from(methodNames);
|
|
46
|
+
if (result.length > 0) {
|
|
47
|
+
console.log(`Extracted error test method names: ${result.join(', ')}`);
|
|
48
|
+
}
|
|
49
|
+
return result.length > 0 ? result : undefined;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=moreUTAutoFixUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moreUTAutoFixUtil.js","sourceRoot":"","sources":["../../src/utils/moreUTAutoFixUtil.ts"],"names":[],"mappings":";;AAQA,kEA4CC;AApDD,uEAA0F;AAE1F;;;;;GAKG;AACH,SAAgB,2BAA2B,CACvC,QAAgB,EAChB,cAAuB,EACvB,WAAiB,EACjB,UAAgB;IAEhB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,IAAI,cAAc,IAAI,WAAW,EAAE,CAAC;QAChC,sDAAsD;QACtD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACrF,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,MAAM,KAAK,GAAG,IAAA,oDAA0B,EAAC,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU;YAC1E,IAAI,KAAK,EAAE,CAAC;gBACR,oCAAoC;gBACpC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAChC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC3E,MAAM,IAAI,GAAG,IAAA,2CAAiB,EAAC,OAAO,CAAC,CAAC;wBACxC,IAAI,IAAI,EAAE,CAAC;4BACP,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;4BACtB,MAAM;wBACV,CAAC;oBACL,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;SAAM,IAAI,CAAC,cAAc,IAAI,UAAU,EAAE,WAAW,EAAE,CAAC;QACpD,8CAA8C;QAC9C,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;YAC1C,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACd,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACjC,CAAC;QACL,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,sCAAsC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC","sourcesContent":["import { findTestMethodRangeByBrace, extractMethodName } from './removeFailedTestMethods';\r\n\r\n/**\r\n * Extract test method names that contain errors from build or test results.\r\n *\r\n * - Build failure: uses error line numbers to find the enclosing test method in the code.\r\n * - Test failure: directly reads failed test names from the test result.\r\n */\r\nexport function extractErrorTestMethodNames(\r\n testCode: string,\r\n isBuildFailure: boolean,\r\n buildResult?: any,\r\n testResult?: any\r\n): string[] {\r\n const methodNames = new Set<string>();\r\n\r\n if (isBuildFailure && buildResult) {\r\n // Build errors: find test method by error line number\r\n const errors = Array.isArray(buildResult) ? buildResult : (buildResult.errors || []);\r\n const lines = testCode?.split('\\n') || [];\r\n for (const err of errors) {\r\n const errorLine = err.line;\r\n if (!errorLine) continue;\r\n const range = findTestMethodRangeByBrace(lines, errorLine - 1); // 0-based\r\n if (range) {\r\n // Find method name within the range\r\n for (let i = range.start; i <= range.end; i++) {\r\n const trimmed = lines[i].trim();\r\n if (!trimmed.startsWith('[') && trimmed !== '' && /\\b\\w+\\s*\\(/.test(trimmed)) {\r\n const name = extractMethodName(trimmed);\r\n if (name) {\r\n methodNames.add(name);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } else if (!isBuildFailure && testResult?.failedTests) {\r\n // Test errors: directly use failed test names\r\n for (const failed of testResult.failedTests) {\r\n if (failed.name) {\r\n methodNames.add(failed.name);\r\n }\r\n }\r\n }\r\n\r\n const result = Array.from(methodNames);\r\n if (result.length > 0) {\r\n console.log(`Extracted error test method names: ${result.join(', ')}`);\r\n }\r\n return result.length > 0 ? result : undefined;\r\n}\r\n"]}
|
|
@@ -2,6 +2,10 @@ import { GenResult } from '../types/genResult';
|
|
|
2
2
|
import { BuildResult } from '../types/buildResult';
|
|
3
3
|
import { TestResult } from '../types/testResult';
|
|
4
4
|
export declare function removeFailedTests(filePath: string, failedTestNames: string[]): string;
|
|
5
|
+
/**
|
|
6
|
+
* extract method name from a method definition line
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractMethodName(line: string): string;
|
|
5
9
|
export declare function removeFailedTestCasesInTestFile(vsTestRes: TestResult, testFilePath: string): void;
|
|
6
10
|
/**
|
|
7
11
|
* Try to remove failed test methods and verify if the remaining code is valid.
|
|
@@ -9,3 +13,11 @@ export declare function removeFailedTestCasesInTestFile(vsTestRes: TestResult, t
|
|
|
9
13
|
* If buildResult has errors, remove the test methods containing build errors and verify.
|
|
10
14
|
*/
|
|
11
15
|
export declare function removeFailedTestMethods(testCode: string, testFilePath: string, testProjectPath: string, sourceCodePath: string, buildResult: BuildResult[] | null, testResult: TestResult | null, isVsPlugin: boolean, originalTestLength?: number): Promise<GenResult | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Find the start and end line indices of the test method containing the given line.
|
|
18
|
+
* Includes all attributes above the test method attribute (e.g., [DataRow], [Category], etc.)
|
|
19
|
+
*/
|
|
20
|
+
export declare function findTestMethodRangeByBrace(lines: string[], targetLineIndex: number): {
|
|
21
|
+
start: number;
|
|
22
|
+
end: number;
|
|
23
|
+
} | null;
|
|
@@ -34,13 +34,29 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.removeFailedTests = removeFailedTests;
|
|
37
|
+
exports.extractMethodName = extractMethodName;
|
|
37
38
|
exports.removeFailedTestCasesInTestFile = removeFailedTestCasesInTestFile;
|
|
38
39
|
exports.removeFailedTestMethods = removeFailedTestMethods;
|
|
40
|
+
exports.findTestMethodRangeByBrace = findTestMethodRangeByBrace;
|
|
39
41
|
const fs = __importStar(require("fs"));
|
|
40
42
|
const constants_1 = require("../types/constants");
|
|
41
43
|
const checkCodeSyntax_1 = require("../analyze/checkCodeSyntax");
|
|
42
44
|
const verifyGeneratedCode_1 = require("./verifyGeneratedCode");
|
|
43
45
|
const fileUtils_1 = require("./fileUtils");
|
|
46
|
+
/**
|
|
47
|
+
* Remove lines at the given 0-based indices from `code`, then collapse
|
|
48
|
+
* consecutive blank / whitespace-only lines down to a single blank line.
|
|
49
|
+
*/
|
|
50
|
+
function removeLinesAndCleanup(code, linesToRemove) {
|
|
51
|
+
if (linesToRemove.size === 0)
|
|
52
|
+
return code;
|
|
53
|
+
const lines = code.split('\n');
|
|
54
|
+
const sorted = Array.from(linesToRemove).sort((a, b) => b - a);
|
|
55
|
+
for (const idx of sorted) {
|
|
56
|
+
lines.splice(idx, 1);
|
|
57
|
+
}
|
|
58
|
+
return lines.join('\n').replace(/(\n\s*){3,}/g, '\n\n');
|
|
59
|
+
}
|
|
44
60
|
function removeFailedTests(filePath, failedTestNames) {
|
|
45
61
|
try {
|
|
46
62
|
if (!fs.existsSync(filePath)) {
|
|
@@ -351,14 +367,7 @@ function removeFailedAssertionsOrMethods(code, errorLines) {
|
|
|
351
367
|
if (linesToRemove.size === 0) {
|
|
352
368
|
return code;
|
|
353
369
|
}
|
|
354
|
-
|
|
355
|
-
const sortedLinesToRemove = Array.from(linesToRemove).sort((a, b) => b - a);
|
|
356
|
-
for (const lineIndex of sortedLinesToRemove) {
|
|
357
|
-
lines.splice(lineIndex, 1);
|
|
358
|
-
}
|
|
359
|
-
// Clean up consecutive empty lines (replace multiple empty lines with single empty line)
|
|
360
|
-
const result = lines.join('\n').replace(/\n{3,}/g, '\n\n');
|
|
361
|
-
return result;
|
|
370
|
+
return removeLinesAndCleanup(code, linesToRemove);
|
|
362
371
|
}
|
|
363
372
|
/**
|
|
364
373
|
* Find all assert statement lines within the given line range.
|
|
@@ -487,14 +496,7 @@ function removeTestMethodsByLines(code, errorLines) {
|
|
|
487
496
|
if (linesToRemove.size === 0) {
|
|
488
497
|
return code;
|
|
489
498
|
}
|
|
490
|
-
|
|
491
|
-
const sortedLinesToRemove = Array.from(linesToRemove).sort((a, b) => b - a);
|
|
492
|
-
for (const lineIndex of sortedLinesToRemove) {
|
|
493
|
-
lines.splice(lineIndex, 1);
|
|
494
|
-
}
|
|
495
|
-
// Clean up consecutive empty lines (replace multiple empty lines with single empty line)
|
|
496
|
-
const result = lines.join('\n').replace(/\n{3,}/g, '\n\n');
|
|
497
|
-
return result;
|
|
499
|
+
return removeLinesAndCleanup(code, linesToRemove);
|
|
498
500
|
}
|
|
499
501
|
/**
|
|
500
502
|
* Find the start and end line indices of the test method containing the given line.
|