ronantakizawa/codereview-bench huggingface dataset:
Repository: rollup/rollup
File: src/utils/deconflictChunk.ts (TypeScript)

Code before:
		}
	}
}

function deconflictTopLevelVariables(
	usedNames: Set<string>,
	modules: readonly Module[],
	includedNamespaces: ReadonlySet<Module>
): void {
	for (const module of modules) {
		module.info.safeVariableNames ||= {};
		for (const variable of module.scope.variables.values()) {
			if (
				variable.included &&
				// this will only happen for exports in some formats
				!(
					variable.renderBaseName ||
					(variable instanceof ExportDefaultVariable && variable.getOriginalVariable() !== variable)
				)
			) {
				const cachedSafeVariableName = Object.getOwnPropertyDescriptor(
					module.info.safeVariableNames,
					variable.name
				)?.value;

				if (cachedSafeVariableName && !usedNames.has(cachedSafeVariableName)) {
					usedNames.add(cachedSafeVariableName);
					variable.setRenderNames(null, cachedSafeVariableName);
					continue;
				}

				variable.setRenderNames(
					null,
					getSafeName(variable.name, usedNames, variable.forbiddenNames)
				);
				module.info.safeVariableNames[variable.name] = variable.renderName!;
			}
		}
		if (includedNamespaces.has(module)) {
			const namespace = module.namespace;
			namespace.setRenderNames(
				null,
				getSafeName(namespace.name, usedNames, namespace.forbiddenNames)
			);
		}
	}
}


Review comment (suggestion):
I understand you are doing it like this because you do not want to get inherited properties. However, if we use an object without prototype or a Map, we could use simple property access (where I think the object without prototype is probably faster).

Code after:
		}
	}
}

function deconflictTopLevelVariables(
	usedNames: Set<string>,
	modules: readonly Module[],
	includedNamespaces: ReadonlySet<Module>
): void {
	for (const module of modules) {
		module.info.safeVariableNames ||= {};
		for (const variable of module.scope.variables.values()) {
			if (
				variable.included &&
				// this will only happen for exports in some formats
				!(
					variable.renderBaseName ||
					(variable instanceof ExportDefaultVariable && variable.getOriginalVariable() !== variable)
				)
			) {
				// We need to make sure that variables that corresponding to object
				// prototype methods are not accidentally matched.
				const cachedSafeVariableName = Object.getOwnPropertyDescriptor(
					module.info.safeVariableNames,
					variable.name
				)?.value;

				if (cachedSafeVariableName && !usedNames.has(cachedSafeVariableName)) {
					usedNames.add(cachedSafeVariableName);
					variable.setRenderNames(null, cachedSafeVariableName);
					continue;
				}

				variable.setRenderNames(
					null,
					getSafeName(variable.name, usedNames, variable.forbiddenNames)
				);
				module.info.safeVariableNames[variable.name] = variable.renderName!;
			}
		}
		if (includedNamespaces.has(module)) {
			const namespace = module.namespace;
			namespace.setRenderNames(
				null,
				getSafeName(namespace.name, usedNames, namespace.forbiddenNames)
			);
		}
	}
}
Repository: rollup/rollup
File: src/utils/deconflictChunk.ts (TypeScript)

Code before:
	modules: readonly Module[],
	includedNamespaces: ReadonlySet<Module>
): void {
	for (const module of modules) {
		module.info.safeVariableNames ||= {};
		for (const variable of module.scope.variables.values()) {
			if (
				variable.included &&
				// this will only happen for exports in some formats
				!(
					variable.renderBaseName ||
					(variable instanceof ExportDefaultVariable && variable.getOriginalVariable() !== variable)
				)
			) {
				const cachedSafeVariableName = Object.getOwnPropertyDescriptor(
					module.info.safeVariableNames,
					variable.name
				)?.value;

				if (cachedSafeVariableName && !usedNames.has(cachedSafeVariableName)) {
					usedNames.add(cachedSafeVariableName);
					variable.setRenderNames(null, cachedSafeVariableName);
					continue;
				}

				variable.setRenderNames(
					null,
					getSafeName(variable.name, usedNames, variable.forbiddenNames)
				);
				module.info.safeVariableNames[variable.name] = variable.renderName!;
			}
		}
		if (includedNamespaces.has(module)) {
			const namespace = module.namespace;
			namespace.setRenderNames(
				null,
				getSafeName(namespace.name, usedNames, namespace.forbiddenNames)
			);
		}
	}
}


Review comment (security):
I see the check for `!usedNames.has(cachedSafeVariableName)` is the secret here to ensure everything is properly deconflicted. Nice work! So the effect is that you always avoid conflicts, but your variable names might "drift" over several builds. Which I think is fine as long as conflicts are always avoided.

Code after:
	modules: readonly Module[],
	includedNamespaces: ReadonlySet<Module>
): void {
	for (const module of modules) {
		module.info.safeVariableNames ||= {};
		for (const variable of module.scope.variables.values()) {
			if (
				variable.included &&
				// this will only happen for exports in some formats
				!(
					variable.renderBaseName ||
					(variable instanceof ExportDefaultVariable && variable.getOriginalVariable() !== variable)
				)
			) {
				// We need to make sure that variables that corresponding to object
				// prototype methods are not accidentally matched.
				const cachedSafeVariableName = Object.getOwnPropertyDescriptor(
					module.info.safeVariableNames,
					variable.name
				)?.value;

				if (cachedSafeVariableName && !usedNames.has(cachedSafeVariableName)) {
					usedNames.add(cachedSafeVariableName);
					variable.setRenderNames(null, cachedSafeVariableName);
					continue;
				}

				variable.setRenderNames(
					null,
					getSafeName(variable.name, usedNames, variable.forbiddenNames)
				);
				module.info.safeVariableNames[variable.name] = variable.renderName!;
			}
		}
		if (includedNamespaces.has(module)) {
			const namespace = module.namespace;
			namespace.setRenderNames(
				null,
				getSafeName(namespace.name, usedNames, namespace.forbiddenNames)
			);
		}
	}
}
Repository: rollup/rollup
File: test/cli/samples/watch/watch-output-contain-input-allowInputInsideOutputPath/rollup.config.mjs (JavaScript)

Code before:
export default [
	{
		input: 'main.js',
		watch: {
			allowInputInsideOutputPath: true,
		},
		output: {
			dir: 'main.js',
			format: 'es'
		}
	},
];


Review comment (suggestion):
Thats not a directory, no? Should it not be like this?

```suggestion
			dir: '',
```

Code after:
export default [
	{
		input: {'out': 'output/main.js'},
		watch: {
			allowInputInsideOutputPath: true,
		},
		output: {
			dir: 'output',
			format: 'es'
		}
	},
];
Repository: rollup/rollup
File: test/form/samples/namespace-optimization-in-operator-synthetic/_config.js (JavaScript)

Code before:
module.exports = defineTest({
	description: 'disables optimization for synthetic named exports when using the in operator',
	options: {
		plugins: [
			{
				name: 'virtual-synthatic',
				resolveId(id) {
					if (id === 'virtual:synthetic') {
						return '\0' + id;
					}
				},
				load(id) {
					if (id === '\0virtual:synthetic') {
						const code = `
							export const __moduleExports = { a: true };
						`;
						return {
							code,
							syntheticNamedExports: '__moduleExports'
						};
					}
				}
			}
		]
	},
	solo: true
});


Review comment (suggestion):
Thanks! One small thing: the local test option `solo` wasn’t removed.

Code after:
module.exports = defineTest({
	description: 'disables optimization for synthetic named exports when using the in operator',
	options: {
		plugins: [
			{
				name: 'virtual-synthatic',
				resolveId(id) {
					if (id === 'virtual:synthetic') {
						return '\0' + id;
					}
				},
				load(id) {
					if (id === '\0virtual:synthetic') {
						const code = `
							export const __moduleExports = { a: true };
						`;
						return {
							code,
							syntheticNamedExports: '__moduleExports'
						};
					}
				}
			}
		]
	}
});
Repository: rollup/rollup
File: src/ast/nodes/shared/BitFlags.ts (TypeScript)

Code before:
	assignmentDeoptimized = 1 << 4,
	bound = 1 << 5,
	isUndefined = 1 << 6,
	optional = 1 << 7,
	async = 1 << 8,
	deoptimizedReturn = 1 << 9,
	computed = 1 << 10,
	hasLostTrack = 1 << 11,
	hasUnknownDeoptimizedInteger = 1 << 12,
	hasUnknownDeoptimizedProperty = 1 << 13,
	directlyIncluded = 1 << 14,
	deoptimizeBody = 1 << 15,
	isBranchResolutionAnalysed = 1 << 16,
	await = 1 << 17,
	method = 1 << 18,
	shorthand = 1 << 19,
	tail = 1 << 20,
	prefix = 1 << 21,
	generator = 1 << 22,
	expression = 1 << 23,
	destructuringDeoptimized = 1 << 24,
	hasDeoptimizedCache = 1 << 25,
	hasEffects = 1 << 26,
	withinTopLevelAwait = 1 << 27,
	checkedForWarnings = 1 << 28,
	shouldBindAttributes = 1 << 29
}

export function isFlagSet(flags: number, flag: Flag): boolean {
	return (flags & flag) !== 0;
}

export function setFlag(flags: number, flag: Flag, value: boolean): number {
	return (flags & ~flag) | (-value & flag);
}


Review comment (suggestion):
If we always bind as I would suggest, we should probably rename the flag, e.g. shouldIncludeDynamicAttributes.

Code after:
	assignmentDeoptimized = 1 << 4,
	bound = 1 << 5,
	isUndefined = 1 << 6,
	optional = 1 << 7,
	async = 1 << 8,
	deoptimizedReturn = 1 << 9,
	computed = 1 << 10,
	hasLostTrack = 1 << 11,
	hasUnknownDeoptimizedInteger = 1 << 12,
	hasUnknownDeoptimizedProperty = 1 << 13,
	directlyIncluded = 1 << 14,
	deoptimizeBody = 1 << 15,
	isBranchResolutionAnalysed = 1 << 16,
	await = 1 << 17,
	method = 1 << 18,
	shorthand = 1 << 19,
	tail = 1 << 20,
	prefix = 1 << 21,
	generator = 1 << 22,
	expression = 1 << 23,
	destructuringDeoptimized = 1 << 24,
	hasDeoptimizedCache = 1 << 25,
	hasEffects = 1 << 26,
	withinTopLevelAwait = 1 << 27,
	checkedForWarnings = 1 << 28,
	shouldIncludeDynamicAttributes = 1 << 29
}

export function isFlagSet(flags: number, flag: Flag): boolean {
	return (flags & flag) !== 0;
}

export function setFlag(flags: number, flag: Flag, value: boolean): number {
	return (flags & ~flag) | (-value & flag);
}
Repository: rollup/rollup
File: test/chunking-form/samples/manual-chunk-not-included/_config.js (JavaScript)

Code before:
module.exports = defineTest({
	description: 'handles manual chunks where the root is not part of the module graph',
	options: {
		input: ['main.js', 'manual-entry.js'],
		output: {
			manualChunks: {
				manual: ['manual-entry.js']
			}
		}
	}
});


Review comment (suggestion):
Now the developer must pass the "manual-entry.js" as an `input`

Code after:
module.exports = defineTest({
	description: 'handles manual chunks where the root is not part of the module graph',
	options: {
		input: ['main.js'],
		output: {
			manualChunks: {
				manual: ['manual-entry.js']
			}
		}
	}
});
Repository: rollup/rollup
File: native.js (JavaScript)

Code before:
const { existsSync } = require('node:fs');
const path = require('node:path');
const { platform, arch, report } = require('node:process');

const isMusl = () => !report.getReport().header.glibcVersionRuntime;
const msvcOrGnu = report.getReport().header.osName.startsWith('MINGW32_NT');

const bindingsByPlatformAndArch = {
	android: {
		arm: { base: 'android-arm-eabi' },
		arm64: { base: 'android-arm64' }
	},
	darwin: {
		arm64: { base: 'darwin-arm64' },
		x64: { base: 'darwin-x64' }
	},
	freebsd: {
		arm64: { base: 'freebsd-arm64' },
		x64: { base: 'freebsd-x64' }
	},
	linux: {
		arm: { base: 'linux-arm-gnueabihf', musl: 'linux-arm-musleabihf' },
		arm64: { base: 'linux-arm64-gnu', musl: 'linux-arm64-musl' },
		loong64: { base: 'linux-loong64-gnu', musl: null },
		ppc64: { base: 'linux-ppc64-gnu', musl: null },
		riscv64: { base: 'linux-riscv64-gnu', musl: 'linux-riscv64-musl' },
		s390x: { base: 'linux-s390x-gnu', musl: null },
		x64: { base: 'linux-x64-gnu', musl: 'linux-x64-musl' }
	},
	openharmony: {
		arm64: { base: 'openharmony-arm64' }

Review comment (suggestion):
I find the name slightly ambiguous, especially since "true" means that it is GNU Windows. But since it is only used in a single place, why not inline it below, then it is completely clear. Also, then it is not evaluated if not needed.
(admittedly, we could also inline isMusl...)

Code after:
const { existsSync } = require('node:fs');
const path = require('node:path');
const { platform, arch, report } = require('node:process');

const isMusl = () => !report.getReport().header.glibcVersionRuntime;

const bindingsByPlatformAndArch = {
	android: {
		arm: { base: 'android-arm-eabi' },
		arm64: { base: 'android-arm64' }
	},
	darwin: {
		arm64: { base: 'darwin-arm64' },
		x64: { base: 'darwin-x64' }
	},
	freebsd: {
		arm64: { base: 'freebsd-arm64' },
		x64: { base: 'freebsd-x64' }
	},
	linux: {
		arm: { base: 'linux-arm-gnueabihf', musl: 'linux-arm-musleabihf' },
		arm64: { base: 'linux-arm64-gnu', musl: 'linux-arm64-musl' },
		loong64: { base: 'linux-loong64-gnu', musl: null },
		ppc64: { base: 'linux-ppc64-gnu', musl: null },
		riscv64: { base: 'linux-riscv64-gnu', musl: 'linux-riscv64-musl' },
		s390x: { base: 'linux-s390x-gnu', musl: null },
		x64: { base: 'linux-x64-gnu', musl: 'linux-x64-musl' }
	},
	openharmony: {
		arm64: { base: 'openharmony-arm64' }
	},
Repository: rollup/rollup
File: native.js (JavaScript)

Code before:
const { existsSync } = require('node:fs');
const path = require('node:path');
const { platform, arch, report } = require('node:process');

const isMusl = () => {
  try {
    return !report.getReport().header.glibcVersionRuntime;
  } catch (_e) {
    return false;
  }
};

const isMingw32 = () => {
  try {
    return report.getReport().header.osName.startsWith('MINGW32_NT');
  } catch (_e) {
    return false;
  }
};

const bindingsByPlatformAndArch = {
	android: {
		arm: { base: 'android-arm-eabi' },
		arm64: { base: 'android-arm64' }
	},
	darwin: {
		arm64: { base: 'darwin-arm64' },
		x64: { base: 'darwin-x64' }
	},
	freebsd: {
		arm64: { base: 'freebsd-arm64' },
		x64: { base: 'freebsd-x64' }
	},

Review comment (suggestion):
JavaScript does indeed support catch without argument [since Node 10](https://node.green/#ES2019-misc-optional-catch-binding)


```suggestion
  } catch {
```

Code after:
const { existsSync } = require('node:fs');
const path = require('node:path');
const { platform, arch, report } = require('node:process');

const isMusl = () => {
	try {
		return !report.getReport().header.glibcVersionRuntime;
	} catch {
		return false;
	}
};

const isMingw32 = () => {
	try {
		return report.getReport().header.osName.startsWith('MINGW32_NT');
	} catch {
		return false;
	}
};

const bindingsByPlatformAndArch = {
	android: {
		arm: { base: 'android-arm-eabi' },
		arm64: { base: 'android-arm64' }
	},
	darwin: {
		arm64: { base: 'darwin-arm64' },
		x64: { base: 'darwin-x64' }
	},
	freebsd: {
		arm64: { base: 'freebsd-arm64' },
		x64: { base: 'freebsd-x64' }
	},
Repository: rollup/rollup
File: src/ast/nodes/VariableDeclarator.ts (TypeScript)

Code before:
			);
		} else if (
			id instanceof Identifier &&
			isReassignedExportsMember(id.variable!, exportNamesByVariable)
		) {
			code.appendLeft(end, `${_}=${_}void 0`);
		}
	}

	includeNode(context: InclusionContext): void {
		this.included = true;
		const { id, init } = this;
		if (init) {
			if (this.isUsingDeclaration) {
				init.includePath(SYMBOL_DISPOSE_PATH, context);
			}
			if (id instanceof Identifier && init instanceof ClassExpression && !init.id) {
				const { name, variable } = id;
				for (const accessedVariable of init.scope.accessedOutsideVariables.values()) {
					if (accessedVariable !== variable) {
						accessedVariable.forbidName(name);
					}
				}
			}
		}
	}
}

VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;

const SYMBOL_DISPOSE_PATH: ObjectPath = [SymbolDispose];


Review comment (bug):
This implementation incorrectly handles `await using` declarations. According to the ECMAScript specification, `using` declarations use Symbol.dispose, while `await using` declarations use Symbol.asyncDispose. Currently, this code always includes the Symbol.dispose path regardless of the declaration type, which means Symbol.asyncDispose handlers will be incorrectly tree-shaken when using `await using` statements.

To fix this, the VariableDeclarator should store the `kind` passed in `declareDeclarator` and use it to determine which symbol path to include (Symbol.dispose for "using" or Symbol.asyncDispose for "await using").

Code after:
				if (renderedVariable !== id.name) {
					code.appendLeft(init.start + 5, ` ${id.name}`);
				}
			}
			init.render(
				code,
				options,
				renderId ? BLANK : { renderedSurroundingElement: NodeType.ExpressionStatement }
			);
		} else if (
			id instanceof Identifier &&
			isReassignedExportsMember(id.variable!, exportNamesByVariable)
		) {
			code.appendLeft(end, `${_}=${_}void 0`);
		}
	}

	includeNode(context: InclusionContext): void {
		this.included = true;
		const { id, init } = this;
		if (init) {
			if (this.isUsingDeclaration) {
				init.includePath(SYMBOL_DISPOSE_PATH, context);
			} else if (this.isAsyncUsingDeclaration) {
				init.includePath(SYMBOL_ASYNC_DISPOSE_PATH, context);
			}
			if (id instanceof Identifier && init instanceof ClassExpression && !init.id) {
				const { name, variable } = id;
				for (const accessedVariable of init.scope.accessedOutsideVariables.values()) {
					if (accessedVariable !== variable) {
						accessedVariable.forbidName(name);
					}
				}
			}
		}
	}
}

VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;

const SYMBOL_DISPOSE_PATH: ObjectPath = [SymbolDispose];
const SYMBOL_ASYNC_DISPOSE_PATH: ObjectPath = [SymbolAsyncDispose];
Repository: rollup/rollup
File: build-plugins/load-cli-help.ts (TypeScript)

Code before:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

const MAX_LINE_LENGTH = 80;

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/[^\n]*\n?/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				finalHelpFile.split('\n').forEach(line => {
					if (line.length > MAX_LINE_LENGTH) {
						throw new Error(`Help file line exceeds ${MAX_LINE_LENGTH} characters:\n${line}`);
					}
				});
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
		},
		name: 'load-help.md'
	};
}


Review comment (suggestion):
The variable name `rawHelpFile` is used in the diff but `helpFile` is used in the validation logic. The validation should use `finalHelpFile` to check the processed content after replacements, not the raw content. This could allow lines that exceed 80 characters after version replacement to pass validation.

Code after:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/\s*#(end)?region[^\n]*\n/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
			return null;
		},
		name: 'load-cli-help'
	};
}
Repository: rollup/rollup
File: build-plugins/load-cli-help.ts (TypeScript)

Code before:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

const MAX_LINE_LENGTH = 80;

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/[^\n]*\n?/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				finalHelpFile.split('\n').forEach(line => {
					if (line.length > MAX_LINE_LENGTH) {
						throw new Error(`Help file line exceeds ${MAX_LINE_LENGTH} characters:\n${line}`);
					}
				});
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
		},
		name: 'load-help.md'
	};
}


Review comment (performance):
The help file is split into lines twice: once for validation and once implicitly when checking line length in the forEach. Consider storing the split result to avoid redundant operations and improve performance.

Code after:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/\s*#(end)?region[^\n]*\n/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
			return null;
		},
		name: 'load-cli-help'
	};
}
Repository: rollup/rollup
File: build-plugins/load-cli-help.ts (TypeScript)

Code before:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/[^\n]*\n?/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
		},
		name: 'load-cli-help'
	};
}


Review comment (suggestion):
The regex pattern matches lines starting with `//` but the pattern `/^\/\/[^\n]*\n?/gm` will match `//` followed by any characters except newline, and then an optional newline. While this works for the current use case with only the region markers, it's fragile. If the help.md file contains lines with `//` that aren't meant to be removed (e.g., in code examples), they would also be stripped. Consider making the pattern more specific to only match the region markers: `.replaceAll(/^\/\/ #(region|endregion) options\n/gm, '')` to be more precise about what should be removed.
```suggestion
					.replaceAll(/^\/\/ #(region|endregion) options\n/gm, '')
```

Code after:
import { readFile } from 'node:fs/promises';
import type { Plugin } from 'rollup';

export default function loadCliHelp(): Plugin {
	return {
		async load(id) {
			if (id.endsWith('help.md')) {
				const [rawHelpFile, packageFile] = await Promise.all([
					readFile(id, 'utf8'),
					readFile(new URL('../package.json', import.meta.url), 'utf8')
				]);
				const finalHelpFile = rawHelpFile
					.replaceAll(/^\/\/\s*#(end)?region[^\n]*\n/gm, '')
					.replace('__VERSION__', JSON.parse(packageFile).version);
				return `export default ${JSON.stringify(finalHelpFile)};`;
			}
			return null;
		},
		name: 'load-cli-help'
	};
}