apex-code-coverage-transformer 2.13.4 → 2.14.1

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +276 -9
  3. package/lib/handlers/BaseHandler.d.ts +51 -0
  4. package/lib/handlers/BaseHandler.js +63 -0
  5. package/lib/handlers/BaseHandler.js.map +1 -0
  6. package/lib/handlers/HandlerRegistry.d.ts +90 -0
  7. package/lib/handlers/HandlerRegistry.js +103 -0
  8. package/lib/handlers/HandlerRegistry.js.map +1 -0
  9. package/lib/handlers/clover.d.ts +16 -2
  10. package/lib/handlers/clover.js +35 -16
  11. package/lib/handlers/clover.js.map +1 -1
  12. package/lib/handlers/cobertura.d.ts +11 -2
  13. package/lib/handlers/cobertura.js +26 -14
  14. package/lib/handlers/cobertura.js.map +1 -1
  15. package/lib/handlers/getHandler.d.ts +24 -0
  16. package/lib/handlers/getHandler.js +27 -19
  17. package/lib/handlers/getHandler.js.map +1 -1
  18. package/lib/handlers/istanbulJson.d.ts +18 -2
  19. package/lib/handlers/istanbulJson.js +35 -2
  20. package/lib/handlers/istanbulJson.js.map +1 -1
  21. package/lib/handlers/jacoco.d.ts +18 -2
  22. package/lib/handlers/jacoco.js +33 -2
  23. package/lib/handlers/jacoco.js.map +1 -1
  24. package/lib/handlers/jsonSummary.d.ts +49 -0
  25. package/lib/handlers/jsonSummary.js +110 -0
  26. package/lib/handlers/jsonSummary.js.map +1 -0
  27. package/lib/handlers/lcov.d.ts +17 -2
  28. package/lib/handlers/lcov.js +29 -9
  29. package/lib/handlers/lcov.js.map +1 -1
  30. package/lib/handlers/opencover.d.ts +71 -0
  31. package/lib/handlers/opencover.js +169 -0
  32. package/lib/handlers/opencover.js.map +1 -0
  33. package/lib/handlers/simplecov.d.ts +50 -0
  34. package/lib/handlers/simplecov.js +90 -0
  35. package/lib/handlers/simplecov.js.map +1 -0
  36. package/lib/handlers/sonar.d.ts +10 -2
  37. package/lib/handlers/sonar.js +21 -3
  38. package/lib/handlers/sonar.js.map +1 -1
  39. package/lib/transformers/coverageTransformer.js +7 -2
  40. package/lib/transformers/coverageTransformer.js.map +1 -1
  41. package/lib/transformers/reportGenerator.d.ts +2 -2
  42. package/lib/transformers/reportGenerator.js +7 -8
  43. package/lib/transformers/reportGenerator.js.map +1 -1
  44. package/lib/utils/buildFilePathCache.d.ts +9 -0
  45. package/lib/utils/buildFilePathCache.js +64 -0
  46. package/lib/utils/buildFilePathCache.js.map +1 -0
  47. package/lib/utils/constants.d.ts +5 -0
  48. package/lib/utils/constants.js +8 -1
  49. package/lib/utils/constants.js.map +1 -1
  50. package/lib/utils/findFilePath.d.ts +8 -1
  51. package/lib/utils/findFilePath.js +26 -35
  52. package/lib/utils/findFilePath.js.map +1 -1
  53. package/lib/utils/types.d.ts +82 -4
  54. package/oclif.manifest.json +8 -5
  55. package/package.json +1 -1
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ import { HandlerRegistry } from './HandlerRegistry.js';
4
+ /**
5
+ * Handler for generating JSON Summary coverage reports.
6
+ *
7
+ * This format provides a concise summary of coverage statistics,
8
+ * ideal for badges, PR comments, and quick analysis.
9
+ *
10
+ * **Format Origin**: Istanbul/NYC coverage tools
11
+ *
12
+ * @see https://istanbul.js.org/
13
+ * @see https://github.com/istanbuljs/nyc
14
+ *
15
+ * **Apex-Specific Adaptations**:
16
+ * - Salesforce Apex only provides line-level coverage data
17
+ * - `statements`, `functions`, and `branches` metrics mirror line coverage
18
+ * - In native JavaScript environments, these would be distinct metrics
19
+ * - `skipped` is always 0 (Apex doesn't report skipped lines)
20
+ *
21
+ * **Limitations**:
22
+ * - No branch coverage (if/else paths) - Apex doesn't provide this data
23
+ * - No function/method coverage separate from lines
24
+ * - No statement coverage distinct from line coverage
25
+ *
26
+ * Compatible with:
27
+ * - GitHub Actions (for badges and PR comments)
28
+ * - GitLab CI (for MR comments)
29
+ * - Custom reporting dashboards
30
+ *
31
+ * @example
32
+ * ```json
33
+ * {
34
+ * "total": {
35
+ * "lines": { "total": 100, "covered": 75, "skipped": 0, "pct": 75 }
36
+ * },
37
+ * "files": {
38
+ * "path/to/file.cls": {
39
+ * "lines": { "total": 50, "covered": 40, "skipped": 0, "pct": 80 }
40
+ * }
41
+ * }
42
+ * }
43
+ * ```
44
+ */
45
+ export class JsonSummaryCoverageHandler extends BaseHandler {
46
+ coverageObj;
47
+ constructor() {
48
+ super();
49
+ this.coverageObj = {
50
+ total: {
51
+ lines: { total: 0, covered: 0, skipped: 0, pct: 0 },
52
+ statements: { total: 0, covered: 0, skipped: 0, pct: 0 },
53
+ },
54
+ files: {},
55
+ };
56
+ }
57
+ processFile(filePath, _fileName, lines) {
58
+ const { totalLines, coveredLines } = this.calculateCoverage(lines);
59
+ const pct = totalLines > 0 ? Number(((coveredLines / totalLines) * 100).toFixed(2)) : 0;
60
+ // NOTE: Apex only provides line coverage, so we use the same values for statements
61
+ // In JavaScript/TypeScript environments, statements would be a distinct metric
62
+ const fileCoverage = {
63
+ lines: {
64
+ total: totalLines,
65
+ covered: coveredLines,
66
+ skipped: 0, // Apex doesn't report skipped lines
67
+ pct,
68
+ },
69
+ statements: {
70
+ total: totalLines, // Using line count as statement count (Apex limitation)
71
+ covered: coveredLines, // Using covered lines as covered statements
72
+ skipped: 0,
73
+ pct,
74
+ },
75
+ };
76
+ this.coverageObj.files[filePath] = fileCoverage;
77
+ // Update totals
78
+ this.coverageObj.total.lines.total += totalLines;
79
+ this.coverageObj.total.lines.covered += coveredLines;
80
+ this.coverageObj.total.statements.total += totalLines;
81
+ this.coverageObj.total.statements.covered += coveredLines;
82
+ }
83
+ finalize() {
84
+ // Calculate total percentages
85
+ const totalLines = this.coverageObj.total.lines.total;
86
+ const totalCovered = this.coverageObj.total.lines.covered;
87
+ if (totalLines > 0) {
88
+ const pct = Number(((totalCovered / totalLines) * 100).toFixed(2));
89
+ this.coverageObj.total.lines.pct = pct;
90
+ this.coverageObj.total.statements.pct = pct;
91
+ }
92
+ // Sort files object by path for deterministic output
93
+ const sortedKeys = Object.keys(this.coverageObj.files).sort();
94
+ const sortedFiles = {};
95
+ for (const key of sortedKeys) {
96
+ sortedFiles[key] = this.coverageObj.files[key];
97
+ }
98
+ this.coverageObj.files = sortedFiles;
99
+ return this.coverageObj;
100
+ }
101
+ }
102
+ // Self-register this handler
103
+ HandlerRegistry.register({
104
+ name: 'json-summary',
105
+ description: 'JSON Summary format for badges and quick analysis',
106
+ fileExtension: '.json',
107
+ handler: () => new JsonSummaryCoverageHandler(),
108
+ compatibleWith: ['GitHub Actions', 'GitLab CI', 'Custom Dashboards'],
109
+ });
110
+ //# sourceMappingURL=jsonSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonSummary.js","sourceRoot":"","sources":["../../src/handlers/jsonSummary.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,20 @@
1
- import { CoverageHandler, LcovCoverageObject } from '../utils/types.js';
2
- export declare class LcovCoverageHandler implements CoverageHandler {
1
+ import { LcovCoverageObject } from '../utils/types.js';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ /**
4
+ * Handler for generating LCOV coverage reports.
5
+ *
6
+ * LCOV is a widely-used format for code coverage reporting,
7
+ * particularly common in JavaScript/Node.js projects.
8
+ *
9
+ * Compatible with:
10
+ * - Codecov
11
+ * - Coveralls
12
+ * - GitHub Actions
13
+ * - LCOV analysis tools
14
+ *
15
+ * @see http://ltp.sourceforge.net/coverage/lcov.php
16
+ */
17
+ export declare class LcovCoverageHandler extends BaseHandler {
3
18
  private readonly coverageObj;
4
19
  constructor();
5
20
  processFile(filePath: string, fileName: string, lines: Record<string, number>): void;
@@ -1,21 +1,33 @@
1
1
  'use strict';
2
- export class LcovCoverageHandler {
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ import { HandlerRegistry } from './HandlerRegistry.js';
4
+ /**
5
+ * Handler for generating LCOV coverage reports.
6
+ *
7
+ * LCOV is a widely-used format for code coverage reporting,
8
+ * particularly common in JavaScript/Node.js projects.
9
+ *
10
+ * Compatible with:
11
+ * - Codecov
12
+ * - Coveralls
13
+ * - GitHub Actions
14
+ * - LCOV analysis tools
15
+ *
16
+ * @see http://ltp.sourceforge.net/coverage/lcov.php
17
+ */
18
+ export class LcovCoverageHandler extends BaseHandler {
3
19
  coverageObj;
4
20
  constructor() {
21
+ super();
5
22
  this.coverageObj = { files: [] };
6
23
  }
7
24
  processFile(filePath, fileName, lines) {
8
- const uncoveredLines = Object.keys(lines)
9
- .filter((lineNumber) => lines[lineNumber] === 0)
10
- .map(Number);
11
- const coveredLines = Object.keys(lines)
12
- .filter((lineNumber) => lines[lineNumber] === 1)
13
- .map(Number);
25
+ const { totalLines, coveredLines } = this.calculateCoverage(lines);
14
26
  const lcovFile = {
15
27
  sourceFile: filePath,
16
28
  lines: [],
17
- totalLines: uncoveredLines.length + coveredLines.length,
18
- coveredLines: coveredLines.length,
29
+ totalLines,
30
+ coveredLines,
19
31
  };
20
32
  for (const [lineNumber, isCovered] of Object.entries(lines)) {
21
33
  lcovFile.lines.push({
@@ -32,4 +44,12 @@ export class LcovCoverageHandler {
32
44
  return this.coverageObj;
33
45
  }
34
46
  }
47
+ // Self-register this handler
48
+ HandlerRegistry.register({
49
+ name: 'lcovonly',
50
+ description: 'LCOV format for JavaScript and C/C++ coverage',
51
+ fileExtension: '.info',
52
+ handler: () => new LcovCoverageHandler(),
53
+ compatibleWith: ['Codecov', 'Coveralls', 'GitHub Actions'],
54
+ });
35
55
  //# sourceMappingURL=lcov.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lcov.js","sourceRoot":"","sources":["../../src/handlers/lcov.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,MAAM,OAAO,mBAAmB;IACb,WAAW,CAAqB;IAEjD;QACE,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACnC,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,KAA6B;QAClF,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aACtC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;aAC/C,GAAG,CAAC,MAAM,CAAC,CAAC;QACf,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aACpC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;aAC/C,GAAG,CAAC,MAAM,CAAC,CAAC;QAEf,MAAM,QAAQ,GAAa;YACzB,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,EAAE;YACT,UAAU,EAAE,cAAc,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM;YACvD,YAAY,EAAE,YAAY,CAAC,MAAM;SAClC,CAAC;QAEF,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAClB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;gBAC9B,QAAQ,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAEM,QAAQ;QACb,IAAI,OAAO,IAAI,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
1
+ {"version":3,"file":"lcov.js","sourceRoot":"","sources":["../../src/handlers/lcov.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IACjC,WAAW,CAAqB;IAEjD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACnC,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,KAA6B;QAClF,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEnE,MAAM,QAAQ,GAAa;YACzB,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,EAAE;YACT,UAAU;YACV,YAAY;SACb,CAAC;QAEF,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAClB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;gBAC9B,QAAQ,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAEM,QAAQ;QACb,IAAI,OAAO,IAAI,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,6BAA6B;AAC7B,eAAe,CAAC,QAAQ,CAAC;IACvB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,+CAA+C;IAC5D,aAAa,EAAE,OAAO;IACtB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,EAAE;IACxC,cAAc,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,gBAAgB,CAAC;CAC3D,CAAC,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { OpenCoverCoverageObject } from '../utils/types.js';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ /**
4
+ * Handler for generating OpenCover XML coverage reports.
5
+ *
6
+ * OpenCover is a code coverage tool for .NET, but its XML format
7
+ * is also accepted by Azure DevOps, Visual Studio, and other tools.
8
+ *
9
+ * **Format Origin**: OpenCover (.NET coverage tool)
10
+ *
11
+ * @see https://github.com/OpenCover/opencover
12
+ * @see https://github.com/OpenCover/opencover/wiki/Reports
13
+ *
14
+ * **Apex-Specific Adaptations**:
15
+ * - Salesforce Apex only provides line-level coverage data
16
+ * - Each Apex class is represented as an OpenCover "Module"
17
+ * - Line coverage is mapped to "SequencePoints" (executable code locations)
18
+ * - Branch coverage is always 0 (Apex doesn't provide branch/decision coverage)
19
+ * - Column information (`@sc`, `@ec`) defaults to 0 (not available in Apex)
20
+ *
21
+ * **Limitations**:
22
+ * - No branch/decision coverage - OpenCover supports this, Apex does not
23
+ * - No method-level coverage granularity - treating entire class as one method
24
+ * - No cyclomatic complexity metrics
25
+ * - No column-level positioning data
26
+ *
27
+ * **Structure Mapping**:
28
+ * - Apex Class → OpenCover Module/Class
29
+ * - Apex Class → OpenCover Method (single method per class)
30
+ * - Apex Lines → OpenCover SequencePoints
31
+ *
32
+ * Compatible with:
33
+ * - Azure DevOps
34
+ * - Visual Studio
35
+ * - Codecov
36
+ * - JetBrains tools (ReSharper, Rider)
37
+ *
38
+ * @example
39
+ * ```xml
40
+ * <CoverageSession>
41
+ * <Summary numSequencePoints="100" visitedSequencePoints="75" />
42
+ * <Modules>
43
+ * <Module>
44
+ * <Files>
45
+ * <File uid="1" fullPath="path/to/file.cls" />
46
+ * </Files>
47
+ * <Classes>
48
+ * <Class fullName="ClassName">
49
+ * <Methods>
50
+ * <Method name="MethodName">
51
+ * <SequencePoints>
52
+ * <SequencePoint vc="1" sl="1" />
53
+ * </SequencePoints>
54
+ * </Method>
55
+ * </Methods>
56
+ * </Class>
57
+ * </Classes>
58
+ * </Module>
59
+ * </Modules>
60
+ * </CoverageSession>
61
+ * ```
62
+ */
63
+ export declare class OpenCoverCoverageHandler extends BaseHandler {
64
+ private readonly coverageObj;
65
+ private readonly module;
66
+ private fileIdCounter;
67
+ private filePathToId;
68
+ constructor();
69
+ processFile(filePath: string, fileName: string, lines: Record<string, number>): void;
70
+ finalize(): OpenCoverCoverageObject;
71
+ }
@@ -0,0 +1,169 @@
1
+ 'use strict';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ import { HandlerRegistry } from './HandlerRegistry.js';
4
+ /**
5
+ * Handler for generating OpenCover XML coverage reports.
6
+ *
7
+ * OpenCover is a code coverage tool for .NET, but its XML format
8
+ * is also accepted by Azure DevOps, Visual Studio, and other tools.
9
+ *
10
+ * **Format Origin**: OpenCover (.NET coverage tool)
11
+ *
12
+ * @see https://github.com/OpenCover/opencover
13
+ * @see https://github.com/OpenCover/opencover/wiki/Reports
14
+ *
15
+ * **Apex-Specific Adaptations**:
16
+ * - Salesforce Apex only provides line-level coverage data
17
+ * - Each Apex class is represented as an OpenCover "Module"
18
+ * - Line coverage is mapped to "SequencePoints" (executable code locations)
19
+ * - Branch coverage is always 0 (Apex doesn't provide branch/decision coverage)
20
+ * - Column information (`@sc`, `@ec`) defaults to 0 (not available in Apex)
21
+ *
22
+ * **Limitations**:
23
+ * - No branch/decision coverage - OpenCover supports this, Apex does not
24
+ * - No method-level coverage granularity - treating entire class as one method
25
+ * - No cyclomatic complexity metrics
26
+ * - No column-level positioning data
27
+ *
28
+ * **Structure Mapping**:
29
+ * - Apex Class → OpenCover Module/Class
30
+ * - Apex Class → OpenCover Method (single method per class)
31
+ * - Apex Lines → OpenCover SequencePoints
32
+ *
33
+ * Compatible with:
34
+ * - Azure DevOps
35
+ * - Visual Studio
36
+ * - Codecov
37
+ * - JetBrains tools (ReSharper, Rider)
38
+ *
39
+ * @example
40
+ * ```xml
41
+ * <CoverageSession>
42
+ * <Summary numSequencePoints="100" visitedSequencePoints="75" />
43
+ * <Modules>
44
+ * <Module>
45
+ * <Files>
46
+ * <File uid="1" fullPath="path/to/file.cls" />
47
+ * </Files>
48
+ * <Classes>
49
+ * <Class fullName="ClassName">
50
+ * <Methods>
51
+ * <Method name="MethodName">
52
+ * <SequencePoints>
53
+ * <SequencePoint vc="1" sl="1" />
54
+ * </SequencePoints>
55
+ * </Method>
56
+ * </Methods>
57
+ * </Class>
58
+ * </Classes>
59
+ * </Module>
60
+ * </Modules>
61
+ * </CoverageSession>
62
+ * ```
63
+ */
64
+ export class OpenCoverCoverageHandler extends BaseHandler {
65
+ coverageObj;
66
+ module;
67
+ fileIdCounter = 1;
68
+ filePathToId = new Map();
69
+ constructor() {
70
+ super();
71
+ this.module = {
72
+ '@hash': 'apex-module',
73
+ Files: { File: [] },
74
+ Classes: { Class: [] },
75
+ };
76
+ this.coverageObj = {
77
+ CoverageSession: {
78
+ Summary: {
79
+ '@numSequencePoints': 0,
80
+ '@visitedSequencePoints': 0,
81
+ '@numBranchPoints': 0,
82
+ '@visitedBranchPoints': 0,
83
+ '@sequenceCoverage': 0,
84
+ '@branchCoverage': 0,
85
+ },
86
+ Modules: {
87
+ Module: [this.module],
88
+ },
89
+ },
90
+ };
91
+ }
92
+ processFile(filePath, fileName, lines) {
93
+ // Register file if not already registered
94
+ if (!this.filePathToId.has(filePath)) {
95
+ const fileId = this.fileIdCounter++;
96
+ this.filePathToId.set(filePath, fileId);
97
+ const fileObj = {
98
+ '@uid': fileId,
99
+ '@fullPath': filePath,
100
+ };
101
+ this.module.Files.File.push(fileObj);
102
+ }
103
+ const { totalLines, coveredLines } = this.calculateCoverage(lines);
104
+ // Create sequence points for each line
105
+ // In OpenCover, a SequencePoint represents an executable statement location
106
+ // We map each Apex line to a SequencePoint
107
+ const sequencePoints = [];
108
+ for (const [lineNumber, hits] of Object.entries(lines)) {
109
+ sequencePoints.push({
110
+ '@vc': hits, // visit count (number of times this line was executed)
111
+ '@sl': Number(lineNumber), // start line
112
+ '@sc': 0, // start column (not available in Apex coverage data)
113
+ '@el': Number(lineNumber), // end line (same as start for line-level coverage)
114
+ '@ec': 0, // end column (not available in Apex coverage data)
115
+ });
116
+ }
117
+ // Create a method for this file
118
+ // NOTE: Apex classes are treated as a single method since we don't have
119
+ // method-level coverage granularity from Salesforce
120
+ const method = {
121
+ '@name': fileName,
122
+ '@isConstructor': false,
123
+ '@isStatic': false,
124
+ SequencePoints: {
125
+ SequencePoint: sequencePoints,
126
+ },
127
+ };
128
+ // Create a class for this file
129
+ const classObj = {
130
+ '@fullName': fileName,
131
+ Methods: {
132
+ Method: [method],
133
+ },
134
+ };
135
+ this.module.Classes.Class.push(classObj);
136
+ // Update summary statistics
137
+ this.coverageObj.CoverageSession.Summary['@numSequencePoints'] += totalLines;
138
+ this.coverageObj.CoverageSession.Summary['@visitedSequencePoints'] += coveredLines;
139
+ }
140
+ finalize() {
141
+ const summary = this.coverageObj.CoverageSession.Summary;
142
+ // Calculate sequence coverage percentage
143
+ if (summary['@numSequencePoints'] > 0) {
144
+ const coverage = (summary['@visitedSequencePoints'] / summary['@numSequencePoints']) * 100;
145
+ summary['@sequenceCoverage'] = Number(coverage.toFixed(2));
146
+ }
147
+ // Branch coverage is always 0 for Apex (no branch/decision coverage data available)
148
+ // In .NET environments, this would track if/else branches, switch cases, etc.
149
+ summary['@branchCoverage'] = 0;
150
+ // Sort classes by name for consistent output
151
+ this.module.Classes.Class.sort((a, b) => a['@fullName'].localeCompare(b['@fullName']));
152
+ // Sort files by path and reassign UIDs sequentially for deterministic output
153
+ this.module.Files.File.sort((a, b) => a['@fullPath'].localeCompare(b['@fullPath']));
154
+ // Reassign UIDs based on sorted order
155
+ for (let i = 0; i < this.module.Files.File.length; i++) {
156
+ this.module.Files.File[i]['@uid'] = i + 1;
157
+ }
158
+ return this.coverageObj;
159
+ }
160
+ }
161
+ // Self-register this handler
162
+ HandlerRegistry.register({
163
+ name: 'opencover',
164
+ description: 'OpenCover XML format for .NET and Azure DevOps',
165
+ fileExtension: '.xml',
166
+ handler: () => new OpenCoverCoverageHandler(),
167
+ compatibleWith: ['Azure DevOps', 'Visual Studio', 'Codecov', 'JetBrains Tools'],
168
+ });
169
+ //# sourceMappingURL=opencover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencover.js","sourceRoot":"","sources":["../../src/handlers/opencover.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAUb,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACtC,WAAW,CAA0B;IACrC,MAAM,CAAkB;IACjC,aAAa,GAAG,CAAC,CAAC;IAClB,YAAY,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEtD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,aAAa;YACtB,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YACnB,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;SACvB,CAAC;QACF,IAAI,CAAC,WAAW,GAAG;YACjB,eAAe,EAAE;gBACf,OAAO,EAAE;oBACP,oBAAoB,EAAE,CAAC;oBACvB,wBAAwB,EAAE,CAAC;oBAC3B,kBAAkB,EAAE,CAAC;oBACrB,sBAAsB,EAAE,CAAC;oBACzB,mBAAmB,EAAE,CAAC;oBACtB,iBAAiB,EAAE,CAAC;iBACrB;gBACD,OAAO,EAAE;oBACP,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;iBACtB;aACF;SACF,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,KAA6B;QAClF,0CAA0C;QAC1C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAExC,MAAM,OAAO,GAAkB;gBAC7B,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,QAAQ;aACtB,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEnE,uCAAuC;QACvC,4EAA4E;QAC5E,2CAA2C;QAC3C,MAAM,cAAc,GAA6B,EAAE,CAAC;QACpD,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,cAAc,CAAC,IAAI,CAAC;gBAClB,KAAK,EAAE,IAAI,EAAE,uDAAuD;gBACpE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,aAAa;gBACxC,KAAK,EAAE,CAAC,EAAE,qDAAqD;gBAC/D,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,mDAAmD;gBAC9E,KAAK,EAAE,CAAC,EAAE,mDAAmD;aAC9D,CAAC,CAAC;QACL,CAAC;QAED,gCAAgC;QAChC,wEAAwE;QACxE,oDAAoD;QACpD,MAAM,MAAM,GAAoB;YAC9B,OAAO,EAAE,QAAQ;YACjB,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE;gBACd,aAAa,EAAE,cAAc;aAC9B;SACF,CAAC;QAEF,+BAA+B;QAC/B,MAAM,QAAQ,GAAmB;YAC/B,WAAW,EAAE,QAAQ;YACrB,OAAO,EAAE;gBACP,MAAM,EAAE,CAAC,MAAM,CAAC;aACjB;SACF,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEzC,4BAA4B;QAC5B,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,UAAU,CAAC;QAC7E,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,wBAAwB,CAAC,IAAI,YAAY,CAAC;IACrF,CAAC;IAEM,QAAQ;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC;QAEzD,yCAAyC;QACzC,IAAI,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,wBAAwB,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,GAAG,CAAC;YAC3F,OAAO,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,oFAAoF;QACpF,8EAA8E;QAC9E,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAE/B,6CAA6C;QAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAEvF,6EAA6E;QAC7E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAEpF,sCAAsC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,6BAA6B;AAC7B,eAAe,CAAC,QAAQ,CAAC;IACvB,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,gDAAgD;IAC7D,aAAa,EAAE,MAAM;IACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,wBAAwB,EAAE;IAC7C,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,CAAC;CAChF,CAAC,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { SimpleCovCoverageObject } from '../utils/types.js';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ /**
4
+ * Handler for generating SimpleCov JSON coverage reports.
5
+ *
6
+ * SimpleCov is a popular Ruby code coverage tool. This format is also
7
+ * accepted by Codecov and other coverage aggregation tools.
8
+ *
9
+ * **Format Origin**: SimpleCov (Ruby coverage tool)
10
+ *
11
+ * @see https://github.com/simplecov-ruby/simplecov
12
+ * @see https://github.com/vicentllongo/simplecov-json
13
+ * @see https://docs.codecov.com/docs/codecov-uploader
14
+ *
15
+ * **Format Structure**:
16
+ * The format uses an array of hit counts per line, with null for non-executable lines.
17
+ * Array indices are 0-based (index 0 = line 1, index 1 = line 2, etc.)
18
+ *
19
+ * **Apex-Specific Adaptations**:
20
+ * - Only lines present in Apex coverage data are tracked
21
+ * - Lines not in coverage data are marked as `null` (non-executable)
22
+ * - This works well with Apex since Salesforce only reports executable lines
23
+ *
24
+ * **Advantages for Apex**:
25
+ * - Simple, compact format
26
+ * - Direct mapping from Apex line coverage to SimpleCov format
27
+ * - Well-supported by Codecov and similar platforms
28
+ *
29
+ * Compatible with:
30
+ * - Codecov
31
+ * - SimpleCov analyzers
32
+ * - Ruby coverage tools
33
+ * - Custom parsers
34
+ *
35
+ * @example
36
+ * ```json
37
+ * {
38
+ * "coverage": {
39
+ * "path/to/file.cls": [1, 1, 0, 1, null, 1]
40
+ * },
41
+ * "timestamp": 1234567890
42
+ * }
43
+ * ```
44
+ */
45
+ export declare class SimpleCovCoverageHandler extends BaseHandler {
46
+ private readonly coverageObj;
47
+ constructor();
48
+ processFile(filePath: string, _fileName: string, lines: Record<string, number>): void;
49
+ finalize(): SimpleCovCoverageObject;
50
+ }
@@ -0,0 +1,90 @@
1
+ 'use strict';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ import { HandlerRegistry } from './HandlerRegistry.js';
4
+ /**
5
+ * Handler for generating SimpleCov JSON coverage reports.
6
+ *
7
+ * SimpleCov is a popular Ruby code coverage tool. This format is also
8
+ * accepted by Codecov and other coverage aggregation tools.
9
+ *
10
+ * **Format Origin**: SimpleCov (Ruby coverage tool)
11
+ *
12
+ * @see https://github.com/simplecov-ruby/simplecov
13
+ * @see https://github.com/vicentllongo/simplecov-json
14
+ * @see https://docs.codecov.com/docs/codecov-uploader
15
+ *
16
+ * **Format Structure**:
17
+ * The format uses an array of hit counts per line, with null for non-executable lines.
18
+ * Array indices are 0-based (index 0 = line 1, index 1 = line 2, etc.)
19
+ *
20
+ * **Apex-Specific Adaptations**:
21
+ * - Only lines present in Apex coverage data are tracked
22
+ * - Lines not in coverage data are marked as `null` (non-executable)
23
+ * - This works well with Apex since Salesforce only reports executable lines
24
+ *
25
+ * **Advantages for Apex**:
26
+ * - Simple, compact format
27
+ * - Direct mapping from Apex line coverage to SimpleCov format
28
+ * - Well-supported by Codecov and similar platforms
29
+ *
30
+ * Compatible with:
31
+ * - Codecov
32
+ * - SimpleCov analyzers
33
+ * - Ruby coverage tools
34
+ * - Custom parsers
35
+ *
36
+ * @example
37
+ * ```json
38
+ * {
39
+ * "coverage": {
40
+ * "path/to/file.cls": [1, 1, 0, 1, null, 1]
41
+ * },
42
+ * "timestamp": 1234567890
43
+ * }
44
+ * ```
45
+ */
46
+ export class SimpleCovCoverageHandler extends BaseHandler {
47
+ coverageObj;
48
+ constructor() {
49
+ super();
50
+ this.coverageObj = {
51
+ coverage: {},
52
+ timestamp: Math.floor(Date.now() / 1000),
53
+ };
54
+ }
55
+ processFile(filePath, _fileName, lines) {
56
+ // Find the maximum line number to determine array size
57
+ const lineNumbers = Object.keys(lines).map(Number);
58
+ const maxLine = Math.max(...lineNumbers);
59
+ // Create array with nulls for non-executable lines
60
+ // SimpleCov uses null to indicate lines that are not executable/trackable
61
+ const lineArray = new Array(maxLine).fill(null);
62
+ // Fill in the coverage data
63
+ // SimpleCov arrays are 0-indexed, but line numbers are 1-indexed
64
+ // So line 1 goes into array index 0, line 2 into index 1, etc.
65
+ for (const [lineNumber, hits] of Object.entries(lines)) {
66
+ const lineIdx = Number(lineNumber) - 1; // Convert to 0-index
67
+ lineArray[lineIdx] = hits; // Store hit count (0 = uncovered, >0 = covered)
68
+ }
69
+ this.coverageObj.coverage[filePath] = lineArray;
70
+ }
71
+ finalize() {
72
+ // Sort coverage object by file path for deterministic output
73
+ const sortedKeys = Object.keys(this.coverageObj.coverage).sort();
74
+ const sortedCoverage = {};
75
+ for (const key of sortedKeys) {
76
+ sortedCoverage[key] = this.coverageObj.coverage[key];
77
+ }
78
+ this.coverageObj.coverage = sortedCoverage;
79
+ return this.coverageObj;
80
+ }
81
+ }
82
+ // Self-register this handler
83
+ HandlerRegistry.register({
84
+ name: 'simplecov',
85
+ description: 'SimpleCov JSON format compatible with Ruby coverage tools',
86
+ fileExtension: '.json',
87
+ handler: () => new SimpleCovCoverageHandler(),
88
+ compatibleWith: ['Codecov', 'SimpleCov', 'Ruby Tools'],
89
+ });
90
+ //# sourceMappingURL=simplecov.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simplecov.js","sourceRoot":"","sources":["../../src/handlers/simplecov.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACtC,WAAW,CAA0B;IAEtD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG;YACjB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;SACzC,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,KAA6B;QACnF,uDAAuD;QACvD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC;QAEzC,mDAAmD;QACnD,0EAA0E;QAC1E,MAAM,SAAS,GAAyB,IAAI,KAAK,CAAgB,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErF,4BAA4B;QAC5B,iEAAiE;QACjE,+DAA+D;QAC/D,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,qBAAqB;YAC7D,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,gDAAgD;QAC7E,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IAClD,CAAC;IAEM,QAAQ;QACb,6DAA6D;QAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACjE,MAAM,cAAc,GAAyC,EAAE,CAAC;QAEhE,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,cAAc,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,cAAc,CAAC;QAE3C,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,6BAA6B;AAC7B,eAAe,CAAC,QAAQ,CAAC;IACvB,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,2DAA2D;IACxE,aAAa,EAAE,OAAO;IACtB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,wBAAwB,EAAE;IAC7C,cAAc,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,CAAC;CACvD,CAAC,CAAC"}
@@ -1,5 +1,13 @@
1
- import { SonarCoverageObject, CoverageHandler } from '../utils/types.js';
2
- export declare class SonarCoverageHandler implements CoverageHandler {
1
+ import { SonarCoverageObject } from '../utils/types.js';
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ /**
4
+ * Handler for generating SonarQube Generic Coverage reports.
5
+ *
6
+ * This is the default format and is compatible with SonarQube and SonarCloud.
7
+ *
8
+ * @see https://docs.sonarqube.org/latest/analysis/generic-test/
9
+ */
10
+ export declare class SonarCoverageHandler extends BaseHandler {
3
11
  private readonly coverageObj;
4
12
  constructor();
5
13
  processFile(filePath: string, _fileName: string, lines: Record<string, number>): void;
@@ -1,7 +1,17 @@
1
1
  'use strict';
2
- export class SonarCoverageHandler {
2
+ import { BaseHandler } from './BaseHandler.js';
3
+ import { HandlerRegistry } from './HandlerRegistry.js';
4
+ /**
5
+ * Handler for generating SonarQube Generic Coverage reports.
6
+ *
7
+ * This is the default format and is compatible with SonarQube and SonarCloud.
8
+ *
9
+ * @see https://docs.sonarqube.org/latest/analysis/generic-test/
10
+ */
11
+ export class SonarCoverageHandler extends BaseHandler {
3
12
  coverageObj;
4
13
  constructor() {
14
+ super();
5
15
  this.coverageObj = { coverage: { '@version': '1', file: [] } };
6
16
  }
7
17
  processFile(filePath, _fileName, lines) {
@@ -10,7 +20,7 @@ export class SonarCoverageHandler {
10
20
  lineToCover: [],
11
21
  };
12
22
  for (const [lineNumberString, value] of Object.entries(lines)) {
13
- const covered = value === 1 ? 'true' : 'false';
23
+ const covered = value === 1;
14
24
  fileObj.lineToCover.push({
15
25
  '@lineNumber': Number(lineNumberString),
16
26
  '@covered': covered,
@@ -20,9 +30,17 @@ export class SonarCoverageHandler {
20
30
  }
21
31
  finalize() {
22
32
  if (this.coverageObj.coverage?.file) {
23
- this.coverageObj.coverage.file.sort((a, b) => a['@path'].localeCompare(b['@path']));
33
+ this.coverageObj.coverage.file = this.sortByPath(this.coverageObj.coverage.file);
24
34
  }
25
35
  return this.coverageObj;
26
36
  }
27
37
  }
38
+ // Self-register this handler
39
+ HandlerRegistry.register({
40
+ name: 'sonar',
41
+ description: 'SonarQube Generic Coverage format',
42
+ fileExtension: '.xml',
43
+ handler: () => new SonarCoverageHandler(),
44
+ compatibleWith: ['SonarQube', 'SonarCloud'],
45
+ });
28
46
  //# sourceMappingURL=sonar.js.map