-
-
Notifications
You must be signed in to change notification settings - Fork 587
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
LingyuCoder
committed
Nov 29, 2023
1 parent
618a5bd
commit ebe9414
Showing
1 changed file
with
146 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,157 @@ | ||
import { ECompareResultType, ECompilerType, ITestReporter, TModuleCompareResult } from "../type"; | ||
import { | ||
ECompareResultType, | ||
ECompilerType, | ||
ITestReporter, | ||
TModuleCompareResult | ||
} from "../type"; | ||
import fs from "fs-extra"; | ||
import csvToMarkdown from "csv-to-markdown-table"; | ||
|
||
export interface IDiffStatsReporterOptions { | ||
header?: string[]; | ||
footer?: string[]; | ||
file: string; | ||
header?: string[]; | ||
footer?: string[]; | ||
file: string; | ||
} | ||
|
||
export type TCompilerTypeId = ECompilerType.Rspack | ECompilerType.Webpack | 'common'; | ||
export type TModuleTypeId = 'normal' | 'runtime'; | ||
export type TDimenTypeId = 'modules' | 'lines' | 'lines-in-common'; | ||
export type TCaseSummaryId = `${TCompilerTypeId}|${TModuleTypeId}|${TDimenTypeId}`; | ||
export type TCompilerTypeId = | ||
| ECompilerType.Rspack | ||
| ECompilerType.Webpack | ||
| "common"; | ||
export type TModuleTypeId = "normal" | "runtime"; | ||
export type TDimenTypeId = "modules" | "lines" | "lines-in-common"; | ||
export type TCaseSummaryId = | ||
`${TCompilerTypeId}|${TModuleTypeId}|${TDimenTypeId}`; | ||
export type TCaseSummary = Record<TCaseSummaryId, number>; | ||
|
||
const toPercent = (d: number) => (d * 100).toFixed(2) + '%'; | ||
const toFirstLetterUpperCase = (s: string) => (s.charAt(0).toUpperCase() + s.slice(1)).split('-').join(' '); | ||
const toPercent = (d: number) => (d * 100).toFixed(2) + "%"; | ||
const toFirstLetterUpperCase = (s: string) => | ||
(s.charAt(0).toUpperCase() + s.slice(1)).split("-").join(" "); | ||
|
||
export class DiffStatsReporter implements ITestReporter<TModuleCompareResult[]> { | ||
private summary: Map<string, TCaseSummary> = new Map(); | ||
private failed: Set<string> = new Set(); | ||
export class DiffStatsReporter | ||
implements ITestReporter<TModuleCompareResult[]> | ||
{ | ||
private summary: Map<string, TCaseSummary> = new Map(); | ||
private failed: Set<string> = new Set(); | ||
|
||
constructor(private options: IDiffStatsReporterOptions) { } | ||
async init(data: TModuleCompareResult[] = []) { } | ||
async failure(id: string) { | ||
this.failed.add(id); | ||
if (this.summary.has(id)) { | ||
this.summary.delete(id); | ||
} | ||
} | ||
async increment(id: string, data: TModuleCompareResult[]) { | ||
if (this.failed.has(id)) return; | ||
if (!this.summary.has(id)) { | ||
this.summary.set(id, this.createSummary()); | ||
} | ||
const current = this.summary.get(id)!; | ||
constructor(private options: IDiffStatsReporterOptions) {} | ||
async init(data: TModuleCompareResult[] = []) {} | ||
async failure(id: string) { | ||
this.failed.add(id); | ||
if (this.summary.has(id)) { | ||
this.summary.delete(id); | ||
} | ||
} | ||
async increment(id: string, data: TModuleCompareResult[]) { | ||
if (this.failed.has(id)) return; | ||
if (!this.summary.has(id)) { | ||
this.summary.set(id, this.createSummary()); | ||
} | ||
const current = this.summary.get(id)!; | ||
|
||
for (let item of data) { | ||
if (item.type === ECompareResultType.Missing) continue; | ||
const moduleType: TModuleTypeId = item.name.startsWith('webpack/runtime') ? 'normal' : 'runtime'; | ||
// handle modules | ||
if (item.type === ECompareResultType.OnlySource) { | ||
current[`${ECompilerType.Rspack}|${moduleType}|${'modules'}`]++; | ||
} else if (item.type === ECompareResultType.OnlyDist) { | ||
current[`${ECompilerType.Webpack}|${moduleType}|${'modules'}`]++; | ||
} else { | ||
// handle lines in common modules | ||
current[`${'common'}|${moduleType}|${'modules'}`]++; | ||
|
||
} | ||
// handle lines | ||
current[`${ECompilerType.Rspack}|${moduleType}|${'lines'}`] += item.lines?.source || 0; | ||
current[`${ECompilerType.Webpack}|${moduleType}|${'lines'}`] += item.lines?.dist || 0; | ||
current[`${'common'}|${moduleType}|${'lines'}`] += item.lines?.common || 0; | ||
|
||
if (item.type === ECompareResultType.Same || item.type === ECompareResultType.Different) { | ||
current[`${ECompilerType.Rspack}|${moduleType}|${'lines-in-common'}`] += item.lines?.source || 0; | ||
current[`${ECompilerType.Webpack}|${moduleType}|${'lines-in-common'}`] += item.lines?.dist || 0; | ||
current[`${'common'}|${moduleType}|${'lines-in-common'}`] += item.lines?.common || 0; | ||
} | ||
} | ||
} | ||
async output() { | ||
const chunks: string[] = []; | ||
for (let [id, summary] of this.summary.entries()) { | ||
chunks.push(this.stringifySummary(id, summary)); | ||
} | ||
for (let id of this.failed.values()) { | ||
chunks.push(`### ${id}\n\n> Failed\n\n`); | ||
} | ||
const output = [...this.options.header || [], chunks.join('\n---\n'), ...this.options.footer || []].join('\n\n'); | ||
fs.ensureFileSync(this.options.file); | ||
fs.writeFileSync(this.options.file, output); | ||
} | ||
private stringifySummary(id: string, summary: TCaseSummary) { | ||
let output = `### ${id}`; | ||
for (let moduleType of ['runtime', 'normal'] as TModuleTypeId[]) { | ||
const csv: string[] = []; | ||
csv.push(`${moduleType.charAt(0).toUpperCase() + moduleType.slice(1)} Modules,Rspack Only,Common,Webpack Only,Common Percent`); | ||
for (let dimen of ['modules', 'lines', 'lines-in-common'] as TDimenTypeId[]) { | ||
const counts = ([ECompilerType.Rspack, 'common', ECompilerType.Webpack] as TCompilerTypeId[]).map(i => summary[`${i}|${moduleType}|${dimen}`]); | ||
csv.push(`${dimen === 'lines-in-common' ? 'Lines(Common Modules)' : toFirstLetterUpperCase(dimen)},${counts.join(',')},${toPercent(counts[1] / (counts[0] + counts[1] + counts[2]))}`); | ||
} | ||
output += csvToMarkdown(csv.join("\n"), ",", true); | ||
output += '\n\n'; | ||
} | ||
return output; | ||
} | ||
private createSummary(): TCaseSummary { | ||
let result: Partial<TCaseSummary> = {}; | ||
for (let i of [ECompilerType.Rspack, ECompilerType.Webpack, 'common'] as TCompilerTypeId[]) { | ||
for (let j of ['runtime', 'normal'] as TModuleTypeId[]) { | ||
for (let k of ['modules', 'lines', 'lines-in-common'] as TDimenTypeId[]) { | ||
result[`${i}|${j}|${k}`] = 0; | ||
} | ||
} | ||
} | ||
return result as TCaseSummary; | ||
} | ||
} | ||
for (let item of data) { | ||
if (item.type === ECompareResultType.Missing) continue; | ||
const moduleType: TModuleTypeId = item.name.startsWith("webpack/runtime") | ||
? "normal" | ||
: "runtime"; | ||
// handle modules | ||
if (item.type === ECompareResultType.OnlySource) { | ||
current[`${ECompilerType.Rspack}|${moduleType}|${"modules"}`]++; | ||
} else if (item.type === ECompareResultType.OnlyDist) { | ||
current[`${ECompilerType.Webpack}|${moduleType}|${"modules"}`]++; | ||
} else { | ||
current[`${"common"}|${moduleType}|${"modules"}`]++; | ||
} | ||
// handle lines | ||
current[`${ECompilerType.Rspack}|${moduleType}|${"lines"}`] += | ||
item.lines?.source || 0; | ||
current[`${ECompilerType.Webpack}|${moduleType}|${"lines"}`] += | ||
item.lines?.dist || 0; | ||
current[`${"common"}|${moduleType}|${"lines"}`] += | ||
item.lines?.common || 0; | ||
// handle lines in common modules | ||
if ( | ||
item.type === ECompareResultType.Same || | ||
item.type === ECompareResultType.Different | ||
) { | ||
current[`${ECompilerType.Rspack}|${moduleType}|${"lines-in-common"}`] += | ||
item.lines?.source || 0; | ||
current[ | ||
`${ECompilerType.Webpack}|${moduleType}|${"lines-in-common"}` | ||
] += item.lines?.dist || 0; | ||
current[`${"common"}|${moduleType}|${"lines-in-common"}`] += | ||
item.lines?.common || 0; | ||
} | ||
} | ||
} | ||
async output() { | ||
const chunks: string[] = []; | ||
for (let [id, summary] of this.summary.entries()) { | ||
chunks.push(this.stringifySummary(id, summary)); | ||
} | ||
for (let id of this.failed.values()) { | ||
chunks.push(`### ${id}\n\n> Failed\n\n`); | ||
} | ||
const output = [ | ||
...(this.options.header || []), | ||
chunks.join("\n---\n"), | ||
...(this.options.footer || []) | ||
].join("\n\n"); | ||
fs.ensureFileSync(this.options.file); | ||
fs.writeFileSync(this.options.file, output); | ||
} | ||
private stringifySummary(id: string, summary: TCaseSummary) { | ||
let output = `### ${id}`; | ||
for (let moduleType of ["runtime", "normal"] as TModuleTypeId[]) { | ||
const csv: string[] = []; | ||
csv.push( | ||
`${ | ||
moduleType.charAt(0).toUpperCase() + moduleType.slice(1) | ||
} Modules,Rspack Only,Common,Webpack Only,Common Percent` | ||
); | ||
for (let dimen of [ | ||
"modules", | ||
"lines", | ||
"lines-in-common" | ||
] as TDimenTypeId[]) { | ||
const counts = ( | ||
[ | ||
ECompilerType.Rspack, | ||
"common", | ||
ECompilerType.Webpack | ||
] as TCompilerTypeId[] | ||
).map(i => summary[`${i}|${moduleType}|${dimen}`]); | ||
csv.push( | ||
`${ | ||
dimen === "lines-in-common" | ||
? "Lines(Common Modules)" | ||
: toFirstLetterUpperCase(dimen) | ||
},${counts.join(",")},${toPercent( | ||
counts[1] / (counts[0] + counts[1] + counts[2]) | ||
)}` | ||
); | ||
} | ||
output += csvToMarkdown(csv.join("\n"), ",", true); | ||
output += "\n\n"; | ||
} | ||
return output; | ||
} | ||
private createSummary(): TCaseSummary { | ||
let result: Partial<TCaseSummary> = {}; | ||
for (let i of [ | ||
ECompilerType.Rspack, | ||
ECompilerType.Webpack, | ||
"common" | ||
] as TCompilerTypeId[]) { | ||
for (let j of ["runtime", "normal"] as TModuleTypeId[]) { | ||
for (let k of [ | ||
"modules", | ||
"lines", | ||
"lines-in-common" | ||
] as TDimenTypeId[]) { | ||
result[`${i}|${j}|${k}`] = 0; | ||
} | ||
} | ||
} | ||
return result as TCaseSummary; | ||
} | ||
} |