• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const fs = require('fs');
17const sourceMap = require('source-map');
18const path = require('path');
19
20const PROJECT_ROOT = path.join(__dirname, '..', '..');
21const COVERAGE_DIR = path.join(PROJECT_ROOT, 'coverage');
22const COVERAGE_FILE = path.join(COVERAGE_DIR, 'coverage.json');
23const NEW_COVERAGE_FILE = path.join(COVERAGE_DIR, 'newCoverage.json');
24
25/**
26 * Processes statement map data using source map consumer
27 * @param {Object} statementMap - Statement map data
28 * @param {Object} consumer - Source map consumer
29 */
30function processStatementMap(statementMap, consumer) {
31    for (const id in statementMap) {
32        const statement = statementMap[id];
33        const startPos = consumer.originalPositionFor(statement.start);
34        const endPos = consumer.originalPositionFor(statement.end);
35
36        statement.start = { line: startPos.line, column: startPos.column };
37        statement.end = { line: endPos.line, column: endPos.column };
38    }
39}
40
41/**
42 * Processes function map data using source map consumer
43 * @param {Object} functionMap - Function map data
44 * @param {Object} consumer - Source map consumer
45 */
46function processFunctionMap(functionMap, consumer) {
47    for (const id in functionMap) {
48        const func = functionMap[id];
49
50        const declStart = consumer.originalPositionFor(func.decl.start);
51        const declEnd = consumer.originalPositionFor(func.decl.end);
52        const locStart = consumer.originalPositionFor(func.loc.start);
53        const locEnd = consumer.originalPositionFor(func.loc.end);
54
55        func.decl = {
56            start: { line: declStart.line, column: declStart.column },
57            end: { line: declEnd.line, column: declEnd.column }
58        };
59
60        func.loc = {
61            start: { line: locStart.line, column: locStart.column },
62            end: { line: locEnd.line, column: locEnd.column }
63        };
64
65        func.line = declStart.line;
66    }
67}
68
69/**
70 * Processes branch map data using source map consumer
71 * @param {Object} branchMap - Branch map data
72 * @param {Object} consumer - Source map consumer
73 */
74function processBranchMap(branchMap, consumer) {
75    for (const id in branchMap) {
76        const branch = branchMap[id];
77
78        // Process locations
79        branch.locations.forEach(location => {
80            const startPos = consumer.originalPositionFor(location.start);
81            const endPos = consumer.originalPositionFor(location.end);
82
83            location.start = { line: startPos.line, column: startPos.column };
84            location.end = { line: endPos.line, column: endPos.column };
85        });
86
87        // Process loc
88        const locStart = consumer.originalPositionFor(branch.loc.start);
89        const locEnd = consumer.originalPositionFor(branch.loc.end);
90
91        branch.loc = {
92            start: { line: locStart.line, column: locStart.column },
93            end: { line: locEnd.line, column: locEnd.column }
94        };
95
96        branch.line = locStart.line;
97    }
98}
99
100/**
101 * Collects and processes coverage data using source maps
102 */
103async function collectCoverage() {
104    if (!fs.existsSync(COVERAGE_FILE)) {
105        throw new Error(`Coverage file not found: ${COVERAGE_FILE}`);
106    }
107
108    const coverageData = JSON.parse(fs.readFileSync(COVERAGE_FILE, 'utf8'));
109    const newCoverageData = {};
110
111    for (const file in coverageData) {
112        const mapFile = `${file}.map`;
113
114        if (!fs.existsSync(mapFile)) {
115            console.warn(`Source map not found for: ${file}`);
116            continue;
117        }
118
119        const sourceMapData = JSON.parse(fs.readFileSync(mapFile, 'utf8'));
120        const sources = sourceMapData.sources;
121        const newFile = path.join(path.dirname(mapFile), sources[0]);
122
123        await sourceMap.SourceMapConsumer.with(sourceMapData, null, (consumer) => {
124            const fileCoverage = { ...coverageData[file] };
125            fileCoverage.path = newFile;
126
127            processStatementMap(fileCoverage.statementMap, consumer);
128            processFunctionMap(fileCoverage.functionMap, consumer);
129            processBranchMap(fileCoverage.branchMap, consumer);
130
131            newCoverageData[newFile] = fileCoverage;
132        });
133    }
134
135    fs.writeFileSync(
136        NEW_COVERAGE_FILE,
137        JSON.stringify(newCoverageData, null, 4)
138    );
139}
140
141// Execute and handle errors
142collectCoverage()
143    .then(() => console.log('Coverage collection completed successfully'))
144    .catch(error => {
145        console.error('Error collecting coverage:', error);
146        process.exit(1);
147    });