@ai-dev-tools/csharp-copilot-core 0.0.31 → 0.0.32
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/analyze/cecil.d.ts +1 -0
- package/out/analyze/cecil.js +42 -0
- package/out/analyze/cecil.js.map +1 -0
- package/out/analyze/checkCodeSyntax.d.ts +7 -0
- package/out/analyze/checkCodeSyntax.js +67 -0
- package/out/analyze/checkCodeSyntax.js.map +1 -0
- package/out/analyze/generateCodeDependency.d.ts +6 -0
- package/out/analyze/generateCodeDependency.js +127 -0
- package/out/analyze/generateCodeDependency.js.map +1 -0
- package/out/analyze/installAnalyzerTool.d.ts +1 -0
- package/out/analyze/installAnalyzerTool.js +83 -0
- package/out/analyze/installAnalyzerTool.js.map +1 -0
- package/out/batch/generateCodeTests.d.ts +6 -0
- package/out/batch/generateCodeTests.js +163 -0
- package/out/batch/generateCodeTests.js.map +1 -0
- package/out/batch/getFolderCodeFile.d.ts +1 -0
- package/out/batch/getFolderCodeFile.js +19 -0
- package/out/batch/getFolderCodeFile.js.map +1 -0
- package/out/batch/getProjectCodeFile.d.ts +4 -0
- package/out/batch/getProjectCodeFile.js +86 -0
- package/out/batch/getProjectCodeFile.js.map +1 -0
- package/out/batch/getSolutionCodeFile.d.ts +8 -0
- package/out/batch/getSolutionCodeFile.js +70 -0
- package/out/batch/getSolutionCodeFile.js.map +1 -0
- package/out/benchmark/formatToMarkdown.d.ts +2 -0
- package/out/benchmark/formatToMarkdown.js +101 -0
- package/out/benchmark/formatToMarkdown.js.map +1 -0
- package/out/benchmark/generateBenchmarkReport.d.ts +1 -0
- package/out/benchmark/generateBenchmarkReport.js +82 -0
- package/out/benchmark/generateBenchmarkReport.js.map +1 -0
- package/out/codeCoverage/codeCoverage.d.ts +6 -0
- package/out/codeCoverage/codeCoverage.js +39 -0
- package/out/codeCoverage/codeCoverage.js.map +1 -0
- package/out/codeCoverage/codeCoverageReport.d.ts +6 -0
- package/out/codeCoverage/codeCoverageReport.js +76 -0
- package/out/codeCoverage/codeCoverageReport.js.map +1 -0
- package/out/codeCoverage/extractCodeCoverageInfo.d.ts +2 -0
- package/out/codeCoverage/extractCodeCoverageInfo.js +81 -0
- package/out/codeCoverage/extractCodeCoverageInfo.js.map +1 -0
- package/out/codeCoverage/extractCoverageReportPath.d.ts +1 -0
- package/out/codeCoverage/extractCoverageReportPath.js +25 -0
- package/out/codeCoverage/extractCoverageReportPath.js.map +1 -0
- package/out/codeCoverage/generateCodeCoverageReport.d.ts +1 -0
- package/out/codeCoverage/generateCodeCoverageReport.js +30 -0
- package/out/codeCoverage/generateCodeCoverageReport.js.map +1 -0
- package/out/codeCoverage/getCodeCoverageSetting.d.ts +1 -0
- package/out/codeCoverage/getCodeCoverageSetting.js +58 -0
- package/out/codeCoverage/getCodeCoverageSetting.js.map +1 -0
- package/out/codeCoverage/reportTool.d.ts +2 -0
- package/out/codeCoverage/reportTool.js +23 -0
- package/out/codeCoverage/reportTool.js.map +1 -0
- package/out/codeCoverage/simplifyCoverageXml.d.ts +2 -0
- package/out/codeCoverage/simplifyCoverageXml.js +117 -0
- package/out/codeCoverage/simplifyCoverageXml.js.map +1 -0
- package/out/codebk/250804prompt/buildAfGuidelines.liquid +15 -0
- package/out/codebk/250804prompt/general/generalBuildAutofixGuidelines.liquid +13 -0
- package/out/codebk/250804prompt/general/generalUtGuidelines.liquid +18 -0
- package/out/codebk/250804prompt/generateUtAutoFix.liquid +19 -0
- package/out/codebk/250804prompt/generateUtGuidelines.liquid +13 -0
- package/out/codebk/250804prompt/generateUtSystem.liquid +5 -0
- package/out/codebk/250804prompt/generateUtUserInput.liquid +27 -0
- package/out/codebk/250804prompt/testAfGuidelines.liquid +6 -0
- package/out/codebk/250804prompt/xap/xapBuildAutofixGuidelines.liquid +13 -0
- package/out/codebk/250804prompt/xap/xapCodeCodeDependency.liquid +0 -0
- package/out/codebk/250804prompt/xap/xapCodeSample.liquid +38 -0
- package/out/codebk/250804prompt/xap/xapUtGuideline-240804.liquid +36 -0
- package/out/codebk/250804prompt/xap/xapUtGuideline.liquid +36 -0
- package/out/codebk/childProcessManager.d.ts +1 -0
- package/out/codebk/childProcessManager.js +50 -0
- package/out/codebk/childProcessManager.js.map +1 -0
- package/out/codebk/msBuidSpawn.d.ts +1 -0
- package/out/codebk/msBuidSpawn.js +58 -0
- package/out/codebk/msBuidSpawn.js.map +1 -0
- package/out/codebk/msBuild.d.ts +1 -0
- package/out/codebk/msBuild.js +123 -0
- package/out/codebk/msBuild.js.map +1 -0
- package/out/codebk/old/generateXapTestAutoFix.liquid +12 -0
- package/out/codebk/old/generateXapTestGuidelines-fm.liquid +68 -0
- package/out/codebk/old/generateXapTestGuidelines.liquid +28 -0
- package/out/codebk/old/xapGuideline-fm.liquid +149 -0
- package/out/codebk/old/xapGuideline.liquid +37 -0
- package/out/codebk/oldExec/checkCodeSyntax.d.ts +1 -0
- package/out/codebk/oldExec/checkCodeSyntax.js +81 -0
- package/out/codebk/oldExec/checkCodeSyntax.js.map +1 -0
- package/out/codebk/oldExec/codeCoverage.d.ts +1 -0
- package/out/codebk/oldExec/codeCoverage.js +54 -0
- package/out/codebk/oldExec/codeCoverage.js.map +1 -0
- package/out/codebk/oldExec/codeCoverageReport.d.ts +1 -0
- package/out/codebk/oldExec/codeCoverageReport.js +64 -0
- package/out/codebk/oldExec/codeCoverageReport.js.map +1 -0
- package/out/codebk/oldExec/containsMethods.d.ts +1 -0
- package/out/codebk/oldExec/containsMethods.js +74 -0
- package/out/codebk/oldExec/containsMethods.js.map +1 -0
- package/out/codebk/oldExec/generateCodeDependency.d.ts +1 -0
- package/out/codebk/oldExec/generateCodeDependency.js +95 -0
- package/out/codebk/oldExec/generateCodeDependency.js.map +1 -0
- package/out/codebk/oldExec/msBuild.d.ts +1 -0
- package/out/codebk/oldExec/msBuild.js +53 -0
- package/out/codebk/oldExec/msBuild.js.map +1 -0
- package/out/codebk/oldExec/vsTest.d.ts +1 -0
- package/out/codebk/oldExec/vsTest.js +71 -0
- package/out/codebk/oldExec/vsTest.js.map +1 -0
- package/out/codebk/prompts/general/generalUnitTestGuidelines-20250702.liquid +56 -0
- package/out/codebk/prompts/generateXapTestGuidelines-20250704.liquid +21 -0
- package/out/codebk/prompts/generateXapTestGuidelines-o.liquid +29 -0
- package/out/codebk/prompts/xap/xapGuideline-o.liquid +45 -0
- package/out/codebk/testbuildkill.d.ts +1 -0
- package/out/codebk/testbuildkill.js +37 -0
- package/out/codebk/testbuildkill.js.map +1 -0
- package/out/command/index.d.ts +2 -0
- package/out/command/index.js +90 -0
- package/out/command/index.js.map +1 -0
- package/out/command/utGenWrapper.d.ts +3 -0
- package/out/command/utGenWrapper.js +53 -0
- package/out/command/utGenWrapper.js.map +1 -0
- package/out/exit/childProcessManager.d.ts +2 -0
- package/out/exit/childProcessManager.js +43 -0
- package/out/exit/childProcessManager.js.map +1 -0
- package/out/exit/setupProcessSignalHandler.d.ts +1 -0
- package/out/exit/setupProcessSignalHandler.js +18 -0
- package/out/exit/setupProcessSignalHandler.js.map +1 -0
- package/out/gen/autoFix.d.ts +4 -0
- package/out/gen/autoFix.js +129 -0
- package/out/gen/autoFix.js.map +1 -0
- package/out/gen/csharpUtGen.d.ts +2 -0
- package/out/gen/csharpUtGen.js +125 -0
- package/out/gen/csharpUtGen.js.map +1 -0
- package/out/gen/ensureValidLLMResponse.d.ts +1 -0
- package/out/gen/ensureValidLLMResponse.js +19 -0
- package/out/gen/ensureValidLLMResponse.js.map +1 -0
- package/out/gen/postGen/addAiAnnotation.d.ts +1 -0
- package/out/gen/postGen/addAiAnnotation.js +57 -0
- package/out/gen/postGen/addAiAnnotation.js.map +1 -0
- package/out/gen/postGen/extractCodeFromResponse.d.ts +1 -0
- package/out/gen/postGen/extractCodeFromResponse.js +38 -0
- package/out/gen/postGen/extractCodeFromResponse.js.map +1 -0
- package/out/gen/postGen/postGenProcess.d.ts +1 -0
- package/out/gen/postGen/postGenProcess.js +39 -0
- package/out/gen/postGen/postGenProcess.js.map +1 -0
- package/out/gen/postGen/removeComments.d.ts +1 -0
- package/out/gen/postGen/removeComments.js +92 -0
- package/out/gen/postGen/removeComments.js.map +1 -0
- package/out/gen/postGen/removeSingleLines.d.ts +1 -0
- package/out/gen/postGen/removeSingleLines.js +29 -0
- package/out/gen/postGen/removeSingleLines.js.map +1 -0
- package/out/gen/postGen/repairRequiredNameSpaces.d.ts +2 -0
- package/out/gen/postGen/repairRequiredNameSpaces.js +142 -0
- package/out/gen/postGen/repairRequiredNameSpaces.js.map +1 -0
- package/out/gen/postGen/validateTestCode.d.ts +1 -0
- package/out/gen/postGen/validateTestCode.js +14 -0
- package/out/gen/postGen/validateTestCode.js.map +1 -0
- package/out/gen/preGen/excludeFileName.d.ts +1 -0
- package/out/gen/preGen/excludeFileName.js +49 -0
- package/out/gen/preGen/excludeFileName.js.map +1 -0
- package/out/gen/preGen/excludeSpecificTag.d.ts +1 -0
- package/out/gen/preGen/excludeSpecificTag.js +19 -0
- package/out/gen/preGen/excludeSpecificTag.js.map +1 -0
- package/out/gen/preGen/preGenProcess.d.ts +1 -0
- package/out/gen/preGen/preGenProcess.js +22 -0
- package/out/gen/preGen/preGenProcess.js.map +1 -0
- package/out/gen/preGen/validateCode.d.ts +3 -0
- package/out/gen/preGen/validateCode.js +63 -0
- package/out/gen/preGen/validateCode.js.map +1 -0
- package/out/index.d.ts +3 -0
- package/out/index.js +10 -0
- package/out/index.js.map +1 -0
- package/out/llm/model/Gpt.d.ts +1 -0
- package/out/llm/model/Gpt.js +93 -0
- package/out/llm/model/Gpt.js.map +1 -0
- package/out/llm/preparePrompt.d.ts +2 -0
- package/out/llm/preparePrompt.js +135 -0
- package/out/llm/preparePrompt.js.map +1 -0
- package/out/llm/prompt/buildAfGuidelines.liquid +15 -0
- package/out/llm/prompt/general/generalBuildAutofixGuidelines.liquid +13 -0
- package/out/llm/prompt/general/generalUtGuidelines.liquid +16 -0
- package/out/llm/prompt/generateUtAutoFix.liquid +23 -0
- package/out/llm/prompt/generateUtDependency.liquid +3 -0
- package/out/llm/prompt/generateUtSystem.liquid +5 -0
- package/out/llm/prompt/generateUtTemplate.liquid +32 -0
- package/out/llm/prompt/generateUtUserInput.liquid +4 -0
- package/out/llm/prompt/xap/xapBuildAutofixGuidelines.liquid +13 -0
- package/out/llm/prompt/xap/xapCodeCodeDependency.liquid +0 -0
- package/out/llm/prompt/xap/xapCodeSample.liquid +38 -0
- package/out/llm/prompt/xap/xapUtGuideline.liquid +37 -0
- package/out/llm/sendRequestToLLM.d.ts +4 -0
- package/out/llm/sendRequestToLLM.js +9 -0
- package/out/llm/sendRequestToLLM.js.map +1 -0
- package/out/llm/sendRequestToSelfHostLLM.d.ts +4 -0
- package/out/llm/sendRequestToSelfHostLLM.js +41 -0
- package/out/llm/sendRequestToSelfHostLLM.js.map +1 -0
- package/out/metrics/appInsightTelemetry.d.ts +6 -0
- package/out/metrics/appInsightTelemetry.js +77 -0
- package/out/metrics/appInsightTelemetry.js.map +1 -0
- package/out/metrics/machineId.d.ts +11 -0
- package/out/metrics/machineId.js +85 -0
- package/out/metrics/machineId.js.map +1 -0
- package/out/setup/setup.d.ts +1 -0
- package/out/setup/setup.js +10 -0
- package/out/setup/setup.js.map +1 -0
- package/out/setup/setupConsole.d.ts +1 -0
- package/out/setup/setupConsole.js +23 -0
- package/out/setup/setupConsole.js.map +1 -0
- package/out/setup/setupLLMRequest.d.ts +2 -0
- package/out/setup/setupLLMRequest.js +10 -0
- package/out/setup/setupLLMRequest.js.map +1 -0
- package/out/tools/devenvcom.cmd +13 -0
- package/out/tools/devenvexe.cmd +13 -0
- package/out/tools/msbuildexe.cmd +13 -0
- package/out/tools/vstestexe.cmd +13 -0
- package/out/types/benchmark.d.ts +11 -0
- package/out/types/benchmark.js +3 -0
- package/out/types/benchmark.js.map +1 -0
- package/out/types/buildResult.d.ts +8 -0
- package/out/types/buildResult.js +3 -0
- package/out/types/buildResult.js.map +1 -0
- package/out/types/constants.d.ts +10 -0
- package/out/types/constants.js +14 -0
- package/out/types/constants.js.map +1 -0
- package/out/types/genResult.d.ts +10 -0
- package/out/types/genResult.js +3 -0
- package/out/types/genResult.js.map +1 -0
- package/out/types/testResult.d.ts +12 -0
- package/out/types/testResult.js +3 -0
- package/out/types/testResult.js.map +1 -0
- package/out/types/verifyResult.d.ts +8 -0
- package/out/types/verifyResult.js +3 -0
- package/out/types/verifyResult.js.map +1 -0
- package/out/utils/checkTestProject.d.ts +2 -0
- package/out/utils/checkTestProject.js +79 -0
- package/out/utils/checkTestProject.js.map +1 -0
- package/out/utils/checkXapCode.d.ts +2 -0
- package/out/utils/checkXapCode.js +59 -0
- package/out/utils/checkXapCode.js.map +1 -0
- package/out/utils/delay.d.ts +1 -0
- package/out/utils/delay.js +7 -0
- package/out/utils/delay.js.map +1 -0
- package/out/utils/detectTestFramework.d.ts +1 -0
- package/out/utils/detectTestFramework.js +33 -0
- package/out/utils/detectTestFramework.js.map +1 -0
- package/out/utils/fileUtils.d.ts +2 -0
- package/out/utils/fileUtils.js +42 -0
- package/out/utils/fileUtils.js.map +1 -0
- package/out/utils/generateCodeSha256.d.ts +1 -0
- package/out/utils/generateCodeSha256.js +46 -0
- package/out/utils/generateCodeSha256.js.map +1 -0
- package/out/utils/getCodeStructurePath.d.ts +5 -0
- package/out/utils/getCodeStructurePath.js +155 -0
- package/out/utils/getCodeStructurePath.js.map +1 -0
- package/out/utils/getOrCreateDir.d.ts +2 -0
- package/out/utils/getOrCreateDir.js +63 -0
- package/out/utils/getOrCreateDir.js.map +1 -0
- package/out/utils/getTestCodeInfo.d.ts +2 -0
- package/out/utils/getTestCodeInfo.js +121 -0
- package/out/utils/getTestCodeInfo.js.map +1 -0
- package/out/utils/getTestFile.d.ts +13 -0
- package/out/utils/getTestFile.js +297 -0
- package/out/utils/getTestFile.js.map +1 -0
- package/out/utils/parseBuildResult.d.ts +3 -0
- package/out/utils/parseBuildResult.js +45 -0
- package/out/utils/parseBuildResult.js.map +1 -0
- package/out/utils/parseSyntaxCheckResult.d.ts +2 -0
- package/out/utils/parseSyntaxCheckResult.js +39 -0
- package/out/utils/parseSyntaxCheckResult.js.map +1 -0
- package/out/utils/parseVstestResult.d.ts +3 -0
- package/out/utils/parseVstestResult.js +62 -0
- package/out/utils/parseVstestResult.js.map +1 -0
- package/out/utils/removeFailedTestMethods.d.ts +3 -0
- package/out/utils/removeFailedTestMethods.js +208 -0
- package/out/utils/removeFailedTestMethods.js.map +1 -0
- package/out/utils/runCommand.d.ts +1 -0
- package/out/utils/runCommand.js +14 -0
- package/out/utils/runCommand.js.map +1 -0
- package/out/utils/spawnExec.d.ts +1 -0
- package/out/utils/spawnExec.js +80 -0
- package/out/utils/spawnExec.js.map +1 -0
- package/out/utils/verifyBuildErrorCausedFile.d.ts +1 -0
- package/out/utils/verifyBuildErrorCausedFile.js +60 -0
- package/out/utils/verifyBuildErrorCausedFile.js.map +1 -0
- package/out/utils/verifyTestCode.d.ts +2 -0
- package/out/utils/verifyTestCode.js +25 -0
- package/out/utils/verifyTestCode.js.map +1 -0
- package/out/utils/writeFailedVerifyResult.d.ts +1 -0
- package/out/utils/writeFailedVerifyResult.js +67 -0
- package/out/utils/writeFailedVerifyResult.js.map +1 -0
- package/out/utils/writeGenCode.d.ts +1 -0
- package/out/utils/writeGenCode.js +63 -0
- package/out/utils/writeGenCode.js.map +1 -0
- package/out/vs/msBuild.d.ts +13 -0
- package/out/vs/msBuild.js +49 -0
- package/out/vs/msBuild.js.map +1 -0
- package/out/vs/vsTest.d.ts +15 -0
- package/out/vs/vsTest.js +75 -0
- package/out/vs/vsTest.js.map +1 -0
- package/out/vs/vsTools.d.ts +7 -0
- package/out/vs/vsTools.js +177 -0
- package/out/vs/vsTools.js.map +1 -0
- package/out/vsPlugin/getVsPluginVerifyResult.d.ts +2 -0
- package/out/vsPlugin/getVsPluginVerifyResult.js +41 -0
- package/out/vsPlugin/getVsPluginVerifyResult.js.map +1 -0
- package/out/vsPlugin/interactionConstants.d.ts +2 -0
- package/out/vsPlugin/interactionConstants.js +10 -0
- package/out/vsPlugin/interactionConstants.js.map +1 -0
- package/out/vsPlugin/sendStdToVsPlugin.d.ts +1 -0
- package/out/vsPlugin/sendStdToVsPlugin.js +12 -0
- package/out/vsPlugin/sendStdToVsPlugin.js.map +1 -0
- package/out/vsPlugin/stdListener.d.ts +3 -0
- package/out/vsPlugin/stdListener.js +57 -0
- package/out/vsPlugin/stdListener.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getExistingTestFile = getExistingTestFile;
|
|
37
|
+
exports.createTestFile = createTestFile;
|
|
38
|
+
exports.getOrCreatTestFile = getOrCreatTestFile;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const getCodeStructurePath_1 = require("./getCodeStructurePath");
|
|
42
|
+
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
43
|
+
const TEST_NAME_REGEX = /(Test|Tests)/i;
|
|
44
|
+
const TEST_ATTR_REGEX = /\[(Fact|Theory|TestClass|TestMethod|Test)\]/;
|
|
45
|
+
function findAllCsprojFiles(dir, excludedPaths) {
|
|
46
|
+
const results = [];
|
|
47
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const fullPath = path.join(dir, entry.name);
|
|
50
|
+
if (entry.name === ".vs" || excludedPaths.includes(fullPath)) {
|
|
51
|
+
continue; // Skip excluded paths
|
|
52
|
+
}
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
results.push(...findAllCsprojFiles(fullPath, excludedPaths));
|
|
55
|
+
}
|
|
56
|
+
else if (entry.isFile() && entry.name.endsWith('.csproj')) {
|
|
57
|
+
results.push(fullPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
function isXapTestProject(csprojPath) {
|
|
63
|
+
try {
|
|
64
|
+
const content = fs.readFileSync(csprojPath, 'utf-8');
|
|
65
|
+
const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false, ignoreDeclaration: true });
|
|
66
|
+
const json = parser.parse(content);
|
|
67
|
+
const project = json.Project;
|
|
68
|
+
const propertyGroups = Array.isArray(project.PropertyGroup)
|
|
69
|
+
? project.PropertyGroup
|
|
70
|
+
: [project.PropertyGroup];
|
|
71
|
+
for (const group of propertyGroups) {
|
|
72
|
+
if (group.XapProjectType === 'TestProject') {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.error(`Failed to parse ${csprojPath}: ${err.message}`);
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
function isGeneralTestProject(csprojPath) {
|
|
83
|
+
try {
|
|
84
|
+
const content = fs.readFileSync(csprojPath, 'utf-8');
|
|
85
|
+
// 1. package reference (test framework)
|
|
86
|
+
const referencesTestFramework = /<PackageReference\s+Include="(xunit|nunit|MSTest\.TestFramework|Microsoft\.NET\.Test\.Sdk)"/i.test(content);
|
|
87
|
+
// 2. file name *.Tests.csproj
|
|
88
|
+
const fileNameHasTests = (/\.Tests\.csproj$/i.test(path.basename(csprojPath))) || (/\.Test\.csproj$/i.test(path.basename(csprojPath)));
|
|
89
|
+
// 3. path contains Tests
|
|
90
|
+
const pathHasTests = /[\\/](Tests?|UnitTests?|IntegrationTests?)[\\/]/i.test(csprojPath);
|
|
91
|
+
// 4. Project SDK is test type (optional)
|
|
92
|
+
const sdkIsTestSdk = /<Project\s+Sdk="Microsoft\.NET\.Test\.Sdk"/i.test(content);
|
|
93
|
+
// 组合判断
|
|
94
|
+
return referencesTestFramework || sdkIsTestSdk || fileNameHasTests || pathHasTests;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.error(`can't read csproj file: ${csprojPath}`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function isFalconUnitTestProject(csprojPath) {
|
|
102
|
+
const xmlContent = fs.readFileSync(csprojPath, 'utf-8');
|
|
103
|
+
const parser = new fast_xml_parser_1.XMLParser({
|
|
104
|
+
ignoreAttributes: false,
|
|
105
|
+
attributeNamePrefix: ''
|
|
106
|
+
});
|
|
107
|
+
const parsed = parser.parse(xmlContent);
|
|
108
|
+
// get PackageReference node
|
|
109
|
+
const project = parsed.Project;
|
|
110
|
+
const itemGroups = Array.isArray(project.ItemGroup) ? project.ItemGroup : [project.ItemGroup];
|
|
111
|
+
let isFalconUnitTestProject = false;
|
|
112
|
+
for (const group of itemGroups) {
|
|
113
|
+
if (!group)
|
|
114
|
+
continue;
|
|
115
|
+
const refs = group.PackageReference;
|
|
116
|
+
if (!refs)
|
|
117
|
+
continue;
|
|
118
|
+
// PackageReference
|
|
119
|
+
const refList = Array.isArray(refs) ? refs : [refs];
|
|
120
|
+
for (const ref of refList) {
|
|
121
|
+
if (ref.Include === 'Microsoft.Falcon.CodeAnalyzers') {
|
|
122
|
+
isFalconUnitTestProject = true;
|
|
123
|
+
console.log('Found Microsoft.Falcon.CodeAnalyzers');
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (isFalconUnitTestProject)
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
// if (!isFalconUnitTestProject) {
|
|
131
|
+
// console.log('Microsoft.Falcon.CodeAnalyzers not found');
|
|
132
|
+
// }
|
|
133
|
+
return isFalconUnitTestProject;
|
|
134
|
+
}
|
|
135
|
+
function isProjectNameMatchedTestProject(csprojPath, projectAssemblyName, projectName) {
|
|
136
|
+
const testProjectName = path.basename(csprojPath, '.csproj').toLowerCase();
|
|
137
|
+
const fileNameEndWithTests = testProjectName.endsWith('.tests') || testProjectName.endsWith('.test') || testProjectName.endsWith('.unittest') || testProjectName.endsWith('.unittests');
|
|
138
|
+
if (testProjectName.startsWith(projectName.toLowerCase()) && fileNameEndWithTests) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
const testProjectAssemblyName = (0, getCodeStructurePath_1.getAssemblyName)(csprojPath);
|
|
142
|
+
return testProjectAssemblyName?.toLowerCase()?.startsWith(projectAssemblyName.toLowerCase()) && fileNameEndWithTests;
|
|
143
|
+
}
|
|
144
|
+
function findTestProjectFromCsFile(csFilePath) {
|
|
145
|
+
let currentDir = path.dirname(csFilePath);
|
|
146
|
+
const repoRoot = (0, getCodeStructurePath_1.getCodeRepoRoot)(csFilePath);
|
|
147
|
+
const projectFilePath = (0, getCodeStructurePath_1.getSourceFileCsprojFilePath)(csFilePath);
|
|
148
|
+
const projectName = path.basename(projectFilePath, '.csproj');
|
|
149
|
+
const projectAssemblyName = (0, getCodeStructurePath_1.getAssemblyName)(projectFilePath);
|
|
150
|
+
const excludedPaths = [currentDir];
|
|
151
|
+
const repoRootParentPath = path.dirname(repoRoot);
|
|
152
|
+
// Start from the parent directory of the source file, because test project is usually in the parent directory
|
|
153
|
+
currentDir = path.dirname(currentDir);
|
|
154
|
+
while (currentDir !== repoRootParentPath) {
|
|
155
|
+
const csprojFiles = findAllCsprojFiles(currentDir, excludedPaths);
|
|
156
|
+
for (const csproj of csprojFiles) {
|
|
157
|
+
if (isProjectNameMatchedTestProject(csproj, projectAssemblyName, projectName)) {
|
|
158
|
+
return csproj;
|
|
159
|
+
}
|
|
160
|
+
else if (isXapTestProject(csproj)) {
|
|
161
|
+
return csproj;
|
|
162
|
+
}
|
|
163
|
+
else if (isFalconUnitTestProject(csproj)) {
|
|
164
|
+
const filename = path.basename(csproj, '.csproj').toLowerCase();
|
|
165
|
+
if (filename.endsWith('unittest') || filename.endsWith('unittests')) {
|
|
166
|
+
return csproj;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else if (isGeneralTestProject(csproj)) {
|
|
170
|
+
return csproj;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Add current directory to excluded paths to avoid re-checking
|
|
174
|
+
excludedPaths.push(currentDir);
|
|
175
|
+
currentDir = path.dirname(currentDir);
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
function findPossibleTestFiles(testProjectDir, className) {
|
|
180
|
+
const results = [];
|
|
181
|
+
const stack = [testProjectDir];
|
|
182
|
+
while (stack.length > 0) {
|
|
183
|
+
const currentDir = stack.pop();
|
|
184
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
185
|
+
for (const entry of entries) {
|
|
186
|
+
if (entry.name === "bin" || entry.name === "obj") {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
190
|
+
if (entry.isDirectory()) {
|
|
191
|
+
stack.push(fullPath);
|
|
192
|
+
}
|
|
193
|
+
else if (entry.isFile() && entry.name.endsWith('.cs') && entry.name.includes(className)) {
|
|
194
|
+
results.push(fullPath);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return results;
|
|
199
|
+
}
|
|
200
|
+
function fileContainsTestAttributes(filePath) {
|
|
201
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
202
|
+
return TEST_ATTR_REGEX.test(content);
|
|
203
|
+
}
|
|
204
|
+
function getExistingTestFile(sourceCodePath) {
|
|
205
|
+
const absPath = path.resolve(sourceCodePath);
|
|
206
|
+
const testProjectPath = findTestProjectFromCsFile(absPath);
|
|
207
|
+
if (!testProjectPath) {
|
|
208
|
+
console.error(`No test project found for ${sourceCodePath}`);
|
|
209
|
+
return { testFilePath: null, testProjectPath: null };
|
|
210
|
+
}
|
|
211
|
+
const testProjectDir = path.dirname(testProjectPath);
|
|
212
|
+
const className = path.basename(sourceCodePath, '.cs');
|
|
213
|
+
const candidateFiles = findPossibleTestFiles(testProjectDir, className);
|
|
214
|
+
for (const testFilePath of candidateFiles) {
|
|
215
|
+
if (TEST_NAME_REGEX.test(path.basename(testFilePath))) {
|
|
216
|
+
return { testFilePath, testProjectPath };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { testFilePath: null, testProjectPath: testProjectPath };
|
|
220
|
+
}
|
|
221
|
+
function createXapTestProject(sourceCodePath) {
|
|
222
|
+
}
|
|
223
|
+
function createTestFile(sourceCodePath) {
|
|
224
|
+
const testProjectPath = findTestProjectFromCsFile(sourceCodePath);
|
|
225
|
+
if (!testProjectPath) {
|
|
226
|
+
console.error(`No test project found for ${sourceCodePath}`);
|
|
227
|
+
return { testFilePath: null, testProjectPath: null };
|
|
228
|
+
}
|
|
229
|
+
const sourceFileName = path.basename(sourceCodePath, '.cs');
|
|
230
|
+
const testFileName = `${sourceFileName}Tests.cs`;
|
|
231
|
+
const sourceFileProjectPath = (0, getCodeStructurePath_1.getSourceFileProjectDir)(sourceCodePath);
|
|
232
|
+
const sourceFileDir = path.dirname(sourceCodePath);
|
|
233
|
+
const testFileRelativePath = sourceFileDir.replace(sourceFileProjectPath, "");
|
|
234
|
+
const testProjecDir = path.dirname(testProjectPath);
|
|
235
|
+
const testFilePath = path.join(testProjecDir, testFileRelativePath, testFileName);
|
|
236
|
+
const testFileDir = path.dirname(testFilePath);
|
|
237
|
+
// Create all missing directories recursively
|
|
238
|
+
fs.mkdirSync(testFileDir, { recursive: true });
|
|
239
|
+
console.log(`Created test file dir at ${testFilePath}`);
|
|
240
|
+
return { testFilePath, testProjectPath };
|
|
241
|
+
}
|
|
242
|
+
function getOrCreatTestFile(sourceCodePath, testFilePath, isXapCode) {
|
|
243
|
+
let finalTestFilePath = testFilePath;
|
|
244
|
+
let finalTestProjectPath;
|
|
245
|
+
let testFileExist = !!testFilePath && fs.existsSync(testFilePath);
|
|
246
|
+
// if outputPath param is not provided, try to find an existing test file
|
|
247
|
+
// if no existing test file found, create a new one in test project
|
|
248
|
+
if (!testFilePath || testFilePath.trim() === '') {
|
|
249
|
+
console.log(' Output path is missing. outputPath:', testFilePath, ', start looking for existing test project');
|
|
250
|
+
let result = getExistingTestFile(sourceCodePath);
|
|
251
|
+
if (result.testFilePath) {
|
|
252
|
+
testFileExist = true;
|
|
253
|
+
console.log(`Found existing test file: ${result.testFilePath}`);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
console.log('No existing test file found, creating a new one.');
|
|
257
|
+
result = createTestFile(sourceCodePath);
|
|
258
|
+
}
|
|
259
|
+
finalTestFilePath = result.testFilePath;
|
|
260
|
+
finalTestProjectPath = result.testProjectPath;
|
|
261
|
+
}
|
|
262
|
+
return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };
|
|
263
|
+
}
|
|
264
|
+
// Example usage
|
|
265
|
+
// const csFilePath = "D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Plugins\\Workflows\\LocationDetection\\AudienceResponseParser.cs";
|
|
266
|
+
// const csFilePath = "D:\\code\\msnews-experiences\\experiences\\weather-right-rail\\src\\WeatherRightRail.connector.ts";
|
|
267
|
+
// const testProjectPath = "D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Tests\\SharedSegments.Tests.csproj";
|
|
268
|
+
// if (!csFilePath) {
|
|
269
|
+
// console.error('Usage: ts-node findTestFile.ts path/to/your/file.cs');
|
|
270
|
+
// process.exit(1);
|
|
271
|
+
// }
|
|
272
|
+
// const start = Date.now();
|
|
273
|
+
// const testFilePath = getExistingTestFile(csFilePath);
|
|
274
|
+
// console.log(`Test file for ${csFilePath}:`, testFilePath ?? 'No test file found');
|
|
275
|
+
// console.log(`Search completed in ${(Date.now() - start) / 1000} seconds`);
|
|
276
|
+
// createXapTestFile(csFilePath);
|
|
277
|
+
// const repoDir = getCodeRepoRoot("D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Plugins\\Workflows\\LocationDetection\\AudienceResponseParser.cs");
|
|
278
|
+
// console.log(`Code repository root directory: ${repoDir}`);
|
|
279
|
+
// const result = getExistingTestFile("D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Plugins\\Workflows\\Eplant\\EplantConfigManager.cs");
|
|
280
|
+
// console.log(`Test file path: ${result.testFilePath}`);
|
|
281
|
+
// console.log(`Test project path: ${result.testProjectPath}`);
|
|
282
|
+
// falcon test project
|
|
283
|
+
// const isFlaconUt = isFalconUnitTestProject("D:\\code\\WeatherNotification\\services\\WeatherUserInterest\\tests\\UnitTests\\Microsoft.Falcon.WeatherUserInterest.UnitTests.csproj");
|
|
284
|
+
// console.log(`Is Falcon Unit Test Project: ${isFlaconUt}`);
|
|
285
|
+
// const testProject = findTestProjectFromCsFile("D:\\code\\WeatherNotification\\services\\WeatherUserInterest\\src\\Service\\Microsoft.Falcon.WeatherUserInterest.csproj");
|
|
286
|
+
// console.log(`Test project path: ${testProject}`);
|
|
287
|
+
// const testFilePath = getOrCreatTestFile("D:\\code\\WeatherNotification\\services\\WeatherUserInterest\\src\\Service\\Components\\IUserInterestTable.cs", undefined, false);
|
|
288
|
+
// console.log(`Test file path: ${testFilePath.testFilePath}`);
|
|
289
|
+
// ads projects
|
|
290
|
+
// const testProjectPath = findTestProjectFromCsFile("D:\\code\\UCMDynamics\\private\\DynamicCode\\Plugin\\UCMDynamics.AppointmentPlugin\\AppointmentOperation.cs");
|
|
291
|
+
// console.log(`Test project path: ${testProjectPath}`);
|
|
292
|
+
// const isValid = isGeneralTestProject("D:\\code\\UCMDynamics\\private\\DynamicCode\\Plugin\\UcmDynamics.AppointmentPlugin\\UcmDynamics.AppointmentPlugin.csproj");
|
|
293
|
+
// // const isValid = isGeneralTestProject("D:\\code\\UCMDynamics\\private\\DynamicCode\\Plugin\\UcmDynamics.AppointmentPlugin.Tests\\UcmDynamics.AppointmentPlugin.Tests.csproj");
|
|
294
|
+
// console.log(`Is General Test Project: ${isValid}`);
|
|
295
|
+
// const testProjectPath = findTestProjectFromCsFile("D:\\code\\AIUnitTestExample\\src\\ToListinator.Analyzers\\ToListCountAnalyzer.cs");
|
|
296
|
+
// console.log(`Test project path: ${testProjectPath}`);
|
|
297
|
+
//# sourceMappingURL=getTestFile.js.map
|
|
@@ -0,0 +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\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\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 fileNameEndWithTests = testProjectName.endsWith('.tests') || testProjectName.endsWith('.test') || testProjectName.endsWith('.unittest') || testProjectName.endsWith('.unittests');\r\n if (testProjectName.startsWith(projectName.toLowerCase()) && fileNameEndWithTests) {\r\n return true;\r\n }\r\n const testProjectAssemblyName = getAssemblyName(csprojPath);\r\n return testProjectAssemblyName?.toLowerCase()?.startsWith(projectAssemblyName.toLowerCase()) && fileNameEndWithTests;\r\n}\r\n\r\nfunction findTestProjectFromCsFile(csFilePath: string): string | null {\r\n let currentDir = path.dirname(csFilePath);\r\n const repoRoot = getCodeRepoRoot(csFilePath);\r\n const projectFilePath = getSourceFileCsprojFilePath(csFilePath);\r\n const projectName = path.basename(projectFilePath, '.csproj');\r\n const projectAssemblyName = getAssemblyName(projectFilePath);\r\n\r\n const excludedPaths: string[] = [currentDir];\r\n const repoRootParentPath = path.dirname(repoRoot);\r\n // Start from the parent directory of the source file, because test project is usually in the parent directory\r\n currentDir = path.dirname(currentDir);\r\n while (currentDir !== repoRootParentPath) {\r\n const csprojFiles = findAllCsprojFiles(currentDir, excludedPaths);\r\n for (const csproj of csprojFiles) {\r\n if (isProjectNameMatchedTestProject(csproj, projectAssemblyName, projectName)) {\r\n return csproj;\r\n } else if (isXapTestProject(csproj)) {\r\n return csproj;\r\n } else if (isFalconUnitTestProject(csproj)) {\r\n const filename = path.basename(csproj, '.csproj').toLowerCase();\r\n if (filename.endsWith('unittest') || filename.endsWith('unittests')) {\r\n return csproj;\r\n }\r\n } else if (isGeneralTestProject(csproj)) {\r\n return csproj;\r\n }\r\n }\r\n // Add current directory to excluded paths to avoid re-checking\r\n excludedPaths.push(currentDir);\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n return null;\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\nexport function getExistingTestFile(sourceCodePath: string) {\r\n const absPath = path.resolve(sourceCodePath);\r\n const testProjectPath = findTestProjectFromCsFile(absPath);\r\n\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 testProjectDir = path.dirname(testProjectPath);\r\n const className = path.basename(sourceCodePath, '.cs');\r\n const candidateFiles = findPossibleTestFiles(testProjectDir, className);\r\n\r\n for (const testFilePath of candidateFiles) {\r\n if (TEST_NAME_REGEX.test(path.basename(testFilePath))) {\r\n return { testFilePath, testProjectPath };\r\n }\r\n }\r\n\r\n return { testFilePath: null, testProjectPath: testProjectPath };\r\n}\r\n\r\nfunction createXapTestProject(sourceCodePath: string) {\r\n}\r\n\r\nexport function createTestFile(sourceCodePath: string) {\r\n const testProjectPath = findTestProjectFromCsFile(sourceCodePath);\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 const sourceFileName = path.basename(sourceCodePath, '.cs');\r\n const testFileName = `${sourceFileName}Tests.cs`;\r\n const sourceFileProjectPath = getSourceFileProjectDir(sourceCodePath);\r\n const sourceFileDir = path.dirname(sourceCodePath);\r\n const testFileRelativePath = sourceFileDir.replace(sourceFileProjectPath, \"\");\r\n const testProjecDir = path.dirname(testProjectPath);\r\n const testFilePath = path.join(testProjecDir, testFileRelativePath, testFileName);\r\n const testFileDir = path.dirname(testFilePath);\r\n // Create all missing directories recursively\r\n fs.mkdirSync(testFileDir, { recursive: true });\r\n console.log(`Created test file dir at ${testFilePath}`);\r\n return { testFilePath, testProjectPath };\r\n}\r\n\r\nexport function getOrCreatTestFile(sourceCodePath: string, testFilePath: string, isXapCode: boolean) {\r\n let finalTestFilePath = testFilePath;\r\n let finalTestProjectPath;\r\n let testFileExist = !!testFilePath && fs.existsSync(testFilePath);\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 if (!testFilePath || testFilePath.trim() === '') {\r\n console.log(' Output path is missing. outputPath:', testFilePath, ', start looking for existing test project');\r\n let result = getExistingTestFile(sourceCodePath);\r\n if (result.testFilePath) {\r\n testFileExist = true;\r\n console.log(`Found existing test file: ${result.testFilePath}`);\r\n } else {\r\n console.log('No existing test file found, creating a new one.');\r\n result = createTestFile(sourceCodePath);\r\n }\r\n finalTestFilePath = result.testFilePath;\r\n finalTestProjectPath = result.testProjectPath;\r\n }\r\n\r\n return { testFilePath: finalTestFilePath, testProjectPath: finalTestProjectPath, testFileExist };\r\n\r\n}\r\n\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,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMsbuildErrors = parseMsbuildErrors;
|
|
4
|
+
exports.formatMsbuildResultToMarkdown = formatMsbuildResultToMarkdown;
|
|
5
|
+
const constants_1 = require("../types/constants");
|
|
6
|
+
function parseMsbuildErrors(buildOutput) {
|
|
7
|
+
const errors = [];
|
|
8
|
+
const lines = buildOutput.split(constants_1.LINESEPARATOR);
|
|
9
|
+
const regex = /^(.+\.cs)\((\d+),(\d+)(?:,\d+,\d+)?\): error (\w+): (.+?) \[(.+)\]$/;
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
const trimmed = line.trim();
|
|
12
|
+
if (!trimmed.includes(': error '))
|
|
13
|
+
continue;
|
|
14
|
+
console.error("build error line:", trimmed);
|
|
15
|
+
const match = regex.exec(trimmed);
|
|
16
|
+
if (match) {
|
|
17
|
+
const [, file, lineStr, columnStr, errorCode, message, project] = match;
|
|
18
|
+
errors.push({
|
|
19
|
+
file,
|
|
20
|
+
line: parseInt(lineStr, 10),
|
|
21
|
+
column: parseInt(columnStr, 10),
|
|
22
|
+
errorCode,
|
|
23
|
+
message,
|
|
24
|
+
project,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return errors;
|
|
29
|
+
}
|
|
30
|
+
function formatMsbuildResultToMarkdown(errors) {
|
|
31
|
+
if (errors.length === 0) {
|
|
32
|
+
return `#### No MSBuild Errors`;
|
|
33
|
+
}
|
|
34
|
+
return errors
|
|
35
|
+
.map(err => {
|
|
36
|
+
const code = `[${err.errorCode}]`;
|
|
37
|
+
const line = `Line ${err.line}`;
|
|
38
|
+
const message = err.message.replace(/\s+/g, ' ').trim();
|
|
39
|
+
return `${code} ${line} - ${message}`;
|
|
40
|
+
})
|
|
41
|
+
.join('\n');
|
|
42
|
+
}
|
|
43
|
+
// const buildError = parseMsbuildErrors("D:\code\CS.Service.Fundamental\SharedSegments\SharedSegments\SharedSegments.Tests\Workflows\Overview\HttpRequestParser\Utils\SqmidHelperTests.cs(37,58): error CS1503: Argument 1: cannot convert from 'int' to 'System.Collections.Generic.IDictionary<string, string>'");
|
|
44
|
+
// console.log(formatMsbuildResultToMarkdown(buildError));
|
|
45
|
+
//# sourceMappingURL=parseBuildResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseBuildResult.js","sourceRoot":"","sources":["../../src/utils/parseBuildResult.ts"],"names":[],"mappings":";;AAGA,gDA0BC;AAED,sEAaC;AA3CD,kDAAmD;AAEnD,SAAgB,kBAAkB,CAAC,WAAmB;IAClD,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,yBAAa,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG,qEAAqE,CAAC;IAEpF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,SAAS;QAE5C,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC;gBACR,IAAI;gBACJ,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC3B,MAAM,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC/B,SAAS;gBACT,OAAO;gBACP,OAAO;aACV,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAgB,6BAA6B,CAAC,MAAqB;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,wBAAwB,CAAC;IACpC,CAAC;IAED,OAAO,MAAM;SACR,GAAG,CAAC,GAAG,CAAC,EAAE;QACP,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,SAAS,GAAG,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACxD,OAAO,GAAG,IAAI,IAAI,IAAI,MAAM,OAAO,EAAE,CAAC;IAC1C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC;AAED,qTAAqT;AACrT,0DAA0D","sourcesContent":["import { BuildResult } from \"../types/buildResult\";\r\nimport { LINESEPARATOR } from \"../types/constants\";\r\n\r\nexport function parseMsbuildErrors(buildOutput: string): BuildResult[] {\r\n const errors: BuildResult[] = [];\r\n const lines = buildOutput.split(LINESEPARATOR);\r\n\r\n const regex = /^(.+\\.cs)\\((\\d+),(\\d+)(?:,\\d+,\\d+)?\\): error (\\w+): (.+?) \\[(.+)\\]$/;\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed.includes(': error ')) continue;\r\n\r\n console.error(\"build error line:\", trimmed);\r\n const match = regex.exec(trimmed);\r\n if (match) {\r\n const [, file, lineStr, columnStr, errorCode, message, project] = match;\r\n errors.push({\r\n file,\r\n line: parseInt(lineStr, 10),\r\n column: parseInt(columnStr, 10),\r\n errorCode,\r\n message,\r\n project,\r\n });\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\nexport function formatMsbuildResultToMarkdown(errors: BuildResult[]): string {\r\n if (errors.length === 0) {\r\n return `#### No MSBuild Errors`;\r\n }\r\n\r\n return errors\r\n .map(err => {\r\n const code = `[${err.errorCode}]`;\r\n const line = `Line ${err.line}`;\r\n const message = err.message.replace(/\\s+/g, ' ').trim();\r\n return `${code} ${line} - ${message}`;\r\n })\r\n .join('\\n');\r\n}\r\n\r\n// const buildError = parseMsbuildErrors(\"D:\\code\\CS.Service.Fundamental\\SharedSegments\\SharedSegments\\SharedSegments.Tests\\Workflows\\Overview\\HttpRequestParser\\Utils\\SqmidHelperTests.cs(37,58): error CS1503: Argument 1: cannot convert from 'int' to 'System.Collections.Generic.IDictionary<string, string>'\");\r\n// console.log(formatMsbuildResultToMarkdown(buildError));"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSyntaxCheckErrors = parseSyntaxCheckErrors;
|
|
4
|
+
const constants_1 = require("../types/constants");
|
|
5
|
+
function parseSyntaxCheckErrors(testFilePath, errorText) {
|
|
6
|
+
const result = [];
|
|
7
|
+
const lines = errorText.split(constants_1.LINESEPARATOR).map(line => line.trim()).filter(line => line.length > 0);
|
|
8
|
+
const regex = /^\((\d+),(\d+)\):\s+error\s+(CS\d+):\s+(.+)$/;
|
|
9
|
+
for (const line of lines) {
|
|
10
|
+
const match = line.match(regex);
|
|
11
|
+
if (match) {
|
|
12
|
+
const [, lineStr, columnStr, errorCode, message] = match;
|
|
13
|
+
result.push({
|
|
14
|
+
file: testFilePath,
|
|
15
|
+
line: Number(lineStr),
|
|
16
|
+
column: Number(columnStr),
|
|
17
|
+
errorCode,
|
|
18
|
+
message,
|
|
19
|
+
project: ""
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
// const buildErrorStr = `
|
|
26
|
+
// (74,62): error CS1513: } expected
|
|
27
|
+
// (74,62): error CS1513: } expected
|
|
28
|
+
// (74,62): error CS1513: } expected
|
|
29
|
+
// (23,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)
|
|
30
|
+
// (36,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)
|
|
31
|
+
// (38,44): error CS0103: The name 'WeatherParameters' does not exist in the current context
|
|
32
|
+
// (48,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)
|
|
33
|
+
// (63,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)
|
|
34
|
+
// `;
|
|
35
|
+
// const buildErrors = parseSyntaxCheckErrors("", buildErrorStr);
|
|
36
|
+
// buildErrors.forEach(err => {
|
|
37
|
+
// console.log(`File: ${err.file}, Line: ${err.line}, Column: ${err.column}, Code: ${err.errorCode}, Message: ${err.message}, Project: ${err.project}`);
|
|
38
|
+
// });
|
|
39
|
+
//# sourceMappingURL=parseSyntaxCheckResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseSyntaxCheckResult.js","sourceRoot":"","sources":["../../src/utils/parseSyntaxCheckResult.ts"],"names":[],"mappings":";;AAGA,wDAuBC;AAzBD,kDAAmD;AAEnD,SAAgB,sBAAsB,CAAC,YAAoB,EAAE,SAAiB;IAC1E,MAAM,MAAM,GAAkB,EAAE,CAAC;IAEjC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,yBAAa,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEtG,MAAM,KAAK,GAAG,8CAA8C,CAAC;IAE7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;gBACzB,SAAS;gBACT,OAAO;gBACP,OAAO,EAAE,EAAE;aACd,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,0BAA0B;AAC1B,oCAAoC;AACpC,oCAAoC;AACpC,oCAAoC;AACpC,yJAAyJ;AACzJ,yJAAyJ;AACzJ,4FAA4F;AAC5F,yJAAyJ;AACzJ,yJAAyJ;AACzJ,KAAK;AAEL,iEAAiE;AACjE,+BAA+B;AAC/B,4JAA4J;AAC5J,MAAM","sourcesContent":["import { BuildResult } from \"../types/buildResult\";\r\nimport { LINESEPARATOR } from \"../types/constants\";\r\n\r\nexport function parseSyntaxCheckErrors(testFilePath: string, errorText: string): BuildResult[] {\r\n const result: BuildResult[] = [];\r\n\r\n const lines = errorText.split(LINESEPARATOR).map(line => line.trim()).filter(line => line.length > 0);\r\n\r\n const regex = /^\\((\\d+),(\\d+)\\):\\s+error\\s+(CS\\d+):\\s+(.+)$/;\r\n\r\n for (const line of lines) {\r\n const match = line.match(regex);\r\n if (match) {\r\n const [, lineStr, columnStr, errorCode, message] = match;\r\n result.push({\r\n file: testFilePath,\r\n line: Number(lineStr),\r\n column: Number(columnStr),\r\n errorCode,\r\n message,\r\n project: \"\"\r\n });\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// const buildErrorStr = `\r\n// (74,62): error CS1513: } expected\r\n// (74,62): error CS1513: } expected\r\n// (74,62): error CS1513: } expected\r\n// (23,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)\r\n// (36,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)\r\n// (38,44): error CS0103: The name 'WeatherParameters' does not exist in the current context\r\n// (48,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)\r\n// (63,60): error CS0246: The type or namespace name 'OneServiceRequest' could not be found (are you missing a using directive or an assembly reference?)\r\n// `;\r\n\r\n// const buildErrors = parseSyntaxCheckErrors(\"\", buildErrorStr);\r\n// buildErrors.forEach(err => {\r\n// console.log(`File: ${err.file}, Line: ${err.line}, Column: ${err.column}, Code: ${err.errorCode}, Message: ${err.message}, Project: ${err.project}`);\r\n// });"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseVSTestOutput = parseVSTestOutput;
|
|
4
|
+
exports.formatVSTestResultToMarkdown = formatVSTestResultToMarkdown;
|
|
5
|
+
const constants_1 = require("../types/constants");
|
|
6
|
+
function parseVSTestOutput(output) {
|
|
7
|
+
const passedTests = [];
|
|
8
|
+
const failedTests = [];
|
|
9
|
+
const lines = output.split(constants_1.LINESEPARATOR);
|
|
10
|
+
let currentFailedTest = null;
|
|
11
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12
|
+
const line = lines[i].trim();
|
|
13
|
+
// Match Passed tests
|
|
14
|
+
const passMatch = line.match(/^Passed (.+) \[/);
|
|
15
|
+
if (passMatch) {
|
|
16
|
+
passedTests.push(passMatch[1]);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
// Match Failed tests
|
|
20
|
+
const failMatch = line.match(/^Failed (.+) \[/);
|
|
21
|
+
if (failMatch) {
|
|
22
|
+
currentFailedTest = {
|
|
23
|
+
name: failMatch[1],
|
|
24
|
+
errorMessage: '',
|
|
25
|
+
stackTrace: ''
|
|
26
|
+
};
|
|
27
|
+
// Read error message
|
|
28
|
+
i += 2; // skip "Error Message:"
|
|
29
|
+
const errorMessageLines = [];
|
|
30
|
+
while (i < lines.length && !lines[i].trim().startsWith('Stack Trace:')) {
|
|
31
|
+
errorMessageLines.push(lines[i].trim());
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
currentFailedTest.errorMessage = errorMessageLines.join('\n');
|
|
35
|
+
// Read stack trace
|
|
36
|
+
i++; // skip "Stack Trace:"
|
|
37
|
+
const stackTraceLines = [];
|
|
38
|
+
while (i < lines.length && lines[i].trim() !== '') {
|
|
39
|
+
stackTraceLines.push(lines[i].trim());
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
currentFailedTest.stackTrace = stackTraceLines.join('\n');
|
|
43
|
+
failedTests.push(currentFailedTest);
|
|
44
|
+
currentFailedTest = null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { passedTests, failedTests, totalTests: passedTests.length + failedTests.length, passed: passedTests.length, failed: failedTests.length };
|
|
48
|
+
}
|
|
49
|
+
function formatVSTestResultToMarkdown(result) {
|
|
50
|
+
const lines = [];
|
|
51
|
+
result.failedTests.forEach(test => {
|
|
52
|
+
const lineNumbers = Array.from(test.stackTrace.matchAll(/:line (\d+)/g)).map(m => m[1]);
|
|
53
|
+
lines.push(`#### ${test.name}`);
|
|
54
|
+
if (lineNumbers.length > 0) {
|
|
55
|
+
lines.push(`**line**: ${lineNumbers.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
lines.push(`**Error Message**: ${test.errorMessage}`);
|
|
58
|
+
lines.push('');
|
|
59
|
+
});
|
|
60
|
+
return lines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=parseVstestResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseVstestResult.js","sourceRoot":"","sources":["../../src/utils/parseVstestResult.ts"],"names":[],"mappings":"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","sourcesContent":["import { LINESEPARATOR } from \"../types/constants\";\r\nimport { FailedTest, TestResult } from \"../types/testResult\";\r\n\r\nexport function parseVSTestOutput(output: string): TestResult {\r\n const passedTests: string[] = [];\r\n const failedTests: FailedTest[] = [];\r\n\r\n const lines = output.split(LINESEPARATOR);\r\n let currentFailedTest: FailedTest | null = null;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i].trim();\r\n\r\n // Match Passed tests\r\n const passMatch = line.match(/^Passed (.+) \\[/);\r\n if (passMatch) {\r\n passedTests.push(passMatch[1]);\r\n continue;\r\n }\r\n\r\n // Match Failed tests\r\n const failMatch = line.match(/^Failed (.+) \\[/);\r\n if (failMatch) {\r\n currentFailedTest = {\r\n name: failMatch[1],\r\n errorMessage: '',\r\n stackTrace: ''\r\n };\r\n\r\n // Read error message\r\n i+=2; // skip \"Error Message:\"\r\n const errorMessageLines: string[] = [];\r\n while (i < lines.length && !lines[i].trim().startsWith('Stack Trace:')) {\r\n errorMessageLines.push(lines[i].trim());\r\n i++;\r\n }\r\n currentFailedTest.errorMessage = errorMessageLines.join('\\n');\r\n\r\n // Read stack trace\r\n i++; // skip \"Stack Trace:\"\r\n const stackTraceLines: string[] = [];\r\n while (i < lines.length && lines[i].trim() !== '') {\r\n stackTraceLines.push(lines[i].trim());\r\n i++;\r\n }\r\n currentFailedTest.stackTrace = stackTraceLines.join('\\n');\r\n\r\n failedTests.push(currentFailedTest);\r\n currentFailedTest = null;\r\n }\r\n }\r\n\r\n return { passedTests, failedTests, totalTests: passedTests.length + failedTests.length, passed: passedTests.length, failed: failedTests.length };\r\n}\r\n\r\n\r\nexport function formatVSTestResultToMarkdown(result: TestResult): string {\r\n const lines: string[] = [];\r\n result.failedTests.forEach(test => {\r\n const lineNumbers = Array.from(\r\n test.stackTrace.matchAll(/:line (\\d+)/g)\r\n ).map(m => m[1]);\r\n\r\n lines.push(`#### ${test.name}`);\r\n if (lineNumbers.length > 0) {\r\n lines.push(`**line**: ${lineNumbers.join(', ')}`);\r\n }\r\n \r\n lines.push(`**Error Message**: ${test.errorMessage}`);\r\n lines.push('');\r\n });\r\n\r\n return lines.join('\\n');\r\n}"]}
|