From 78fe54c69a5796f1fca244cf6a733374c4701e3c Mon Sep 17 00:00:00 2001 From: cenfun Date: Mon, 18 Dec 2023 10:36:31 +0800 Subject: [PATCH] refactor converter --- lib/converter/converter.js | 365 +++++++++++++++++++------------------ 1 file changed, 185 insertions(+), 180 deletions(-) diff --git a/lib/converter/converter.js b/lib/converter/converter.js index 89d2f45d..10b2eccd 100644 --- a/lib/converter/converter.js +++ b/lib/converter/converter.js @@ -23,6 +23,7 @@ const getDistAstInfo = (item, state) => { const source = positionMapping.source; const type = item.type; + // css also support, but css need handle something like: @charset "UTF-8"; const comments = []; const ast = acornLoose.parse(source, { ecmaVersion: 'latest', @@ -42,7 +43,7 @@ const getDistAstInfo = (item, state) => { const functions = []; if (type === 'js') { acornWalk.simple(ast, { - // Function include FunctionDeclaration, ArrowFunctionExpression, FunctionExpression + // Function include FunctionDeclaration, ArrowFunctionExpression, FunctionExpression Function(node) { const functionName = node.id && node.id.name; functions.push({ @@ -51,6 +52,9 @@ const getDistAstInfo = (item, state) => { functionName }); } + + // maybe branches later + }); functions.sort((a, b) => { return a.start - b.start; @@ -83,129 +87,6 @@ const updateLineComment = (positionMapping, range) => { }; -const getEmptyCoverage = () => { - - // from ast - const ranges = []; - const branches = []; - - // from ast - const comments = []; - - // from ast - const functions = []; - const functionMap = new Map(); - - // no comments for now, after ast - const lines = []; - const lineMap = {}; - - const blankCount = 0; - const commentCount = 0; - - return { - - ranges, - branches, - - comments, - - functions, - functionMap, - - lines, - lineMap, - - blankCount, - commentCount - }; -}; - -const initDistFileCoverage = (item, state) => { - - const coverage = getEmptyCoverage(); - - const { type } = item; - const { positionMapping, astInfo } = state; - - // comments - const comments = astInfo.comments; - // add comment marked to lines - comments.forEach((range) => { - updateLineComment(positionMapping, range); - }); - - // functions only for js - if (type === 'js') { - const functions = []; - const functionMap = new Map(); - astInfo.functions.forEach((fun) => { - const { - start, end, functionName - } = fun; - const sLoc = positionMapping.offsetToLocation(start); - const eLoc = positionMapping.offsetToLocation(end); - const functionInfo = new InfoFunction(sLoc, eLoc, 0, functionName); - - const { line, column } = sLoc; - - // line: { column: } - let funLineMap = functionMap.get(line); - if (!funLineMap) { - funLineMap = new Map(); - functionMap.set(line, funLineMap); - } - funLineMap.set(column, functionInfo); - - functions.push(functionInfo); - }); - - coverage.functions = functions; - coverage.functionMap = functionMap; - - } - - // add all lines - const lines = []; - const lineMap = {}; - - // init lines - let blankCount = 0; - let commentCount = 0; - - // baseLineCount: - // js: 1 (functions include all uncovered) - // css: 0 (ranges include all covered) - let baseLineCount = 0; - if (type === 'js') { - baseLineCount = 1; - } - - positionMapping.lines.forEach((it) => { - // exclude blank and comment - if (it.blank) { - blankCount += 1; - return; - } - if (it.comment) { - commentCount += 1; - return; - } - // line 1-base - const line = it.line + 1; - const lineInfo = new InfoLine(line, it.length, baseLineCount); - lineMap[line] = lineInfo; - lines.push(lineInfo); - }); - - coverage.lines = lines; - coverage.lineMap = lineMap; - coverage.blankCount = blankCount; - coverage.commentCount = commentCount; - - return coverage; -}; - // ======================================================================================================== const calculateV8Functions = (functions) => { @@ -259,6 +140,42 @@ const calculateV8Lines = (lines, blankCount, commentCount) => { return v8Lines; }; +const createEmptyCoverage = () => { + + // comments ranges from ast + const comments = []; + + const branches = []; + + // functions ranges from ast + const functions = []; + const functionMap = new Map(); + + const lines = []; + const lineMap = new Map(); + + const blankCount = 0; + const commentCount = 0; + + // coverage ranges from coverage API + const ranges = []; + + return { + comments, + + branches, + + functions, + functionMap, + + lines, + lineMap, + blankCount, + commentCount, + + ranges + }; +}; // istanbul coverage format /** @@ -273,17 +190,18 @@ const calculateV8Lines = (lines, blankCount, commentCount) => { const getFileCoverage = (coverage, sourcePath) => { const { - lines, + comments, - blankCount, - commentCount, + branches, functions, - branches, - ranges, + lines, + blankCount, + commentCount, + + ranges - comments } = coverage; // istanbul @@ -334,7 +252,7 @@ const getFileCoverage = (coverage, sourcePath) => { // ======================================================================================================== const setLineCount = (lineMap, line, count) => { - const lineInfo = lineMap[line]; + const lineInfo = lineMap.get(line); if (lineInfo) { lineInfo.count = count; } @@ -523,34 +441,114 @@ const addCssCoverage = (coverage, range, positionMapping) => { // ======================================================================================================== -const getDistCoverage = (item, state) => { - const { type } = item; +const handleDistFunctionsCoverage = (item, state, coverage) => { + + // functions only for js + if (item.type !== 'js') { + return; + } + + const { positionMapping, astInfo } = state; + + const functions = coverage.functions; + const functionMap = coverage.functionMap; + astInfo.functions.forEach((fun) => { + const { + start, end, functionName + } = fun; + const sLoc = positionMapping.offsetToLocation(start); + const eLoc = positionMapping.offsetToLocation(end); + const functionInfo = new InfoFunction(sLoc, eLoc, 0, functionName); + + const { line, column } = sLoc; + + // line: { column: } + let funLineMap = functionMap.get(line); + if (!funLineMap) { + funLineMap = new Map(); + functionMap.set(line, funLineMap); + } + funLineMap.set(column, functionInfo); + + functions.push(functionInfo); + }); + +}; + +const handleDistLinesCoverage = (item, state, coverage) => { + + const { positionMapping, astInfo } = state; + + const lines = coverage.lines; + const lineMap = coverage.lineMap; + + // init lines + let blankCount = 0; + let commentCount = 0; + + // baseLineCount: + // js: 1 (functions include all uncovered) + // css: 0 (ranges include all covered) + const baseLineCount = item.type === 'js' ? 1 : 0; + + // handle comment before collect lines + const comments = astInfo.comments; + + // keep comments ranges for UI (after pretty print) + coverage.comments = comments; + + // console.log('comments =================', item.sourcePath, comments.length); + // add comment marked to lines + comments.forEach((range) => { + updateLineComment(positionMapping, range); + }); + + positionMapping.lines.forEach((it) => { + // exclude blank and comment + if (it.blank) { + blankCount += 1; + return; + } + if (it.comment) { + commentCount += 1; + return; + } + // line 1-base + const line = it.line + 1; + const lineInfo = new InfoLine(line, it.length, baseLineCount); + lineMap.set(line, lineInfo); + lines.push(lineInfo); + }); + + coverage.blankCount = blankCount; + coverage.commentCount = commentCount; +}; + +const handleDistRangesCoverage = (item, state, coverage) => { + const { positionMapping } = state; - // js file - if (type === 'js') { - const coverage = initDistFileCoverage(item, state); + if (item.type === 'js') { state.functions.forEach((block) => { block.ranges.forEach((range, index) => { addJsCoverage(coverage, block, range, index, positionMapping); }); }); - - return coverage; + } else { + state.ranges.forEach((range) => { + addCssCoverage(coverage, range, positionMapping); + }); } - - // css file - const coverage = initDistFileCoverage(item, state); - state.ranges.forEach((range) => { - addCssCoverage(coverage, range, positionMapping); - }); - return coverage; }; -const unpackDistSource = (item, state) => { +const generateCoverageForDist = (item, state) => { - const coverage = getDistCoverage(item, state); - state.coverage = coverage; + const coverage = createEmptyCoverage(); + + // handle coverage + handleDistFunctionsCoverage(item, state, coverage); + handleDistLinesCoverage(item, state, coverage); + handleDistRangesCoverage(item, state, coverage); const sourcePath = item.sourcePath; const { v8Coverage, istanbulCoverage } = getFileCoverage(coverage, sourcePath); @@ -689,7 +687,7 @@ const initOriginalList = (item, state, originalDecodedMap, options) => { const decodedMappings = getOriginalDecodedMappings(originalDecodedMap, sourceIndex, positionMapping); // unpacked file always is js - const coverage = getEmptyCoverage(); + const coverage = createEmptyCoverage(); const type = getSourceType(sourcePath); @@ -708,7 +706,7 @@ const initOriginalList = (item, state, originalDecodedMap, options) => { return originalMap; }; -const generateOriginalList = (item, state, originalMap) => { +const collectOriginalList = (item, state, originalMap) => { const { fileUrls, sourceMap } = state; const distFile = sourceMap.file || path.basename(item.sourcePath); @@ -749,33 +747,8 @@ const generateOriginalList = (item, state, originalMap) => { return sourceList; }; -const unpackSourceMap = async (item, state, options) => { - - const { type, sourcePath } = item; - const sourceMap = state.sourceMap; - - // keep original urls - const fileUrls = {}; - const sourcePathHandler = options.sourcePath; - initSourceMapSourcePath(sourceMap, fileUrls, sourcePathHandler); - state.fileUrls = fileUrls; - - // =============================================== - // decode mappings for each original file - const time_start_decode = Date.now(); - const originalDecodedMap = new Map(); - // for find-original-range - state.decodedMappings = await decodeSourceMappings(item, state, originalDecodedMap); - // only debug level - Util.logTime(`decode source mappings: ${sourcePath}`, time_start_decode); - - // filter original list and init list - const originalMap = initOriginalList(item, state, originalDecodedMap, options); - - originalDecodedMap.clear(); - - // =============================================== - +const addCoverageForOriginal = (item, state, originalMap) => { + const { type } = item; const astInfo = state.astInfo; // comment count //TODO @@ -783,6 +756,7 @@ const unpackSourceMap = async (item, state, options) => { }); + // =============================================== // const time_start_mapping = Date.now(); if (type === 'js') { @@ -810,9 +784,40 @@ const unpackSourceMap = async (item, state, options) => { // support css later // current css no sourceMap, so never come in } +}; + +const unpackSourceMap = async (item, state, options) => { + + const { sourcePath } = item; + const sourceMap = state.sourceMap; + + // keep original urls + const fileUrls = {}; + const sourcePathHandler = options.sourcePath; + initSourceMapSourcePath(sourceMap, fileUrls, sourcePathHandler); + state.fileUrls = fileUrls; + + // =============================================== + // decode mappings for each original file + const time_start_decode = Date.now(); + const originalDecodedMap = new Map(); + // for find-original-range + state.decodedMappings = await decodeSourceMappings(item, state, originalDecodedMap); + // only debug level + Util.logTime(`decode source mappings: ${sourcePath}`, time_start_decode); + + // filter original list and init list + const originalMap = initOriginalList(item, state, originalDecodedMap, options); + + originalDecodedMap.clear(); + + // =============================================== + + // convert mapping + addCoverageForOriginal(item, state, originalMap); // collect list - state.sourceList = generateOriginalList(item, state, originalMap); + state.sourceList = collectOriginalList(item, state, originalMap); }; @@ -826,7 +831,7 @@ const unpackDistFile = async (item, state, options) => { if (state.sourceMap) { if (Util.loggingType === 'debug') { // js self - unpackDistSource(item, state); + generateCoverageForDist(item, state); } else { item.dedupe = true; } @@ -837,7 +842,7 @@ const unpackDistFile = async (item, state, options) => { } else { // css/js self - unpackDistSource(item, state); + generateCoverageForDist(item, state); }