Skip to content

Commit 01d7638

Browse files
committed
Adds watching support for contributions.json
1 parent be322ca commit 01d7638

File tree

2 files changed

+75
-44
lines changed

2 files changed

+75
-44
lines changed

scripts/generateContributions.mts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ const extract = args.indexOf('--extract') >= 0;
3333
const validate = args.indexOf('--validate') >= 0;
3434

3535
if (extract) {
36-
console.log('Extracting contributions from package.json into contributions.json...');
3736
extractContributionsFromPackageJson();
3837
} else {
39-
console.log('Generating contributions into package.json from contributions.json...');
4038
generateContributionsIntoPackageJson();
4139
}
4240

4341
/** Generates the `contributions.json` from the contributes configuration in `package.json` */
4442
function extractContributionsFromPackageJson(): void {
43+
console.log('Extracting contributions from package.json into contributions.json...');
44+
4545
const commands = new Map<string, CommandDefinition>();
4646
const submenus = new Map<string, SubmenuDefinition>();
4747
const keybindings: ContributionsJson['keybindings'] = [];
@@ -276,6 +276,8 @@ function extractContributionsFromPackageJson(): void {
276276

277277
/** Generates the contributes configuration from `contributions.json` into `package.json` */
278278
function generateContributionsIntoPackageJson(): void {
279+
console.log("Generating 'package.json' contributions from contributions.json...");
280+
279281
const builder = new ContributesBuilder();
280282
builder.load(path.join(__dirname, 'contributions.json'));
281283
const contributions = builder.build();
@@ -288,15 +290,29 @@ function generateContributionsIntoPackageJson(): void {
288290
validateContributions(packageJson.contributes, contributions);
289291
}
290292

293+
// Skip writing if there are no changes
294+
if (
295+
JSON.stringify(packageJson.contributes.commands) === JSON.stringify(contributions.commands) &&
296+
JSON.stringify(packageJson.contributes.keybindings) === JSON.stringify(contributions.keybindings) &&
297+
JSON.stringify(packageJson.contributes.submenus) === JSON.stringify(contributions.submenus) &&
298+
JSON.stringify(packageJson.contributes.menus) === JSON.stringify(contributions.menus) &&
299+
JSON.stringify(packageJson.contributes.views) === JSON.stringify(contributions.views) &&
300+
JSON.stringify(packageJson.contributes.viewsWelcome) === JSON.stringify(contributions.viewsWelcome)
301+
) {
302+
console.log("Skipped; No changes detected in 'contributions.json'");
303+
return;
304+
}
305+
291306
// Update package.json
292307
packageJson.contributes.commands = contributions.commands;
308+
packageJson.contributes.keybindings = contributions.keybindings;
293309
packageJson.contributes.menus = contributions.menus;
294310
packageJson.contributes.submenus = contributions.submenus;
295-
packageJson.contributes.keybindings = contributions.keybindings;
296311
packageJson.contributes.views = contributions.views;
297312
packageJson.contributes.viewsWelcome = contributions.viewsWelcome;
298313

299314
writeFileSync(path.join(__dirname, 'package.json'), `${JSON.stringify(packageJson, undefined, '\t')}\n`, 'utf8');
315+
console.log("Generated 'package.json' contributions");
300316
}
301317

302318
/** Validates that all existing contributions are preserved in the new contributions */

webpack.config.mjs

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -725,58 +725,73 @@ const schema = {
725725
};
726726

727727
class ContributionsPlugin {
728-
alreadyRun = false;
729-
730728
constructor() {
731729
this.pluginName = 'contributions';
730+
this.lastModified = 0;
732731
}
733732

734733
/**
735734
* @param {import("webpack").Compiler} compiler
736735
*/
737736
apply(compiler) {
738-
/**
739-
* @this {ContributionsPlugin}
740-
* @param {import("webpack").Compiler} compiler
741-
*/
742-
async function generate(compiler) {
743-
if (compiler.watchMode) {
744-
if (this.alreadyRun) return;
745-
this.alreadyRun = true;
746-
}
747-
748-
const logger = compiler.getInfrastructureLogger(this.pluginName);
749-
logger.log(`Generating contributions...`);
737+
const contributesPath = path.join(__dirname, 'contributions.json');
738+
let pendingGeneration = false;
750739

751-
const start = Date.now();
740+
// Add file dependency for watching
741+
compiler.hooks.thisCompilation.tap(this.pluginName, compilation => {
742+
// Only watch the source file
743+
compilation.fileDependencies.add(contributesPath);
744+
});
752745

753-
const result = spawnSync('pnpm', ['run', 'generate:contributions'], {
754-
cwd: __dirname,
755-
encoding: 'utf8',
756-
shell: true,
757-
});
746+
// Run generation when needed
747+
compiler.hooks.make.tapAsync(this.pluginName, async (compilation, callback) => {
748+
const logger = compiler.getInfrastructureLogger(this.pluginName);
749+
try {
750+
const stats = fs.statSync(contributesPath);
751+
// Only regenerate if the file has changed since last time
752+
if (stats.mtimeMs <= this.lastModified) {
753+
callback();
754+
return;
755+
}
756+
757+
// Avoid duplicate runs
758+
if (pendingGeneration) {
759+
callback();
760+
return;
761+
}
762+
763+
pendingGeneration = true;
764+
765+
try {
766+
logger.log(`[${compiler.name}] Generating 'package.json' contributions...`);
767+
const start = Date.now();
768+
769+
const result = spawnSync('pnpm', ['run', 'generate:contributions'], {
770+
cwd: __dirname,
771+
encoding: 'utf8',
772+
shell: true,
773+
});
758774

759-
if (result.status === 0) {
760-
logger.log(`Generated contributions in \x1b[32m${Date.now() - start}ms\x1b[0m`);
761-
} else {
762-
logger.error(`Failed to generate contributions: ${result.stderr}`);
775+
if (result.status === 0) {
776+
this.lastModified = Date.now();
777+
logger.log(
778+
`[${compiler.name}] Generated 'package.json' contributions in \x1b[32m${
779+
Date.now() - start
780+
}ms\x1b[0m`,
781+
);
782+
} else {
783+
logger.error(`[${this.pluginName}] Failed to generate contributions: ${result.stderr}`);
784+
}
785+
} finally {
786+
pendingGeneration = false;
787+
}
788+
} catch (err) {
789+
// File doesn't exist or other error
790+
logger.error(`[${this.pluginName}] Error checking contributions file: ${err}`);
763791
}
764-
}
765-
766-
const generateFn = generate.bind(this);
767-
compiler.hooks.beforeRun.tapPromise(this.pluginName, generateFn);
768-
compiler.hooks.watchRun.tapPromise(this.pluginName, generateFn);
769792

770-
// Add contributes.json to watch files
771-
if (compiler.options.plugins) {
772-
compiler.options.plugins.push({
773-
apply: compiler => {
774-
compiler.hooks.afterCompile.tap(this.pluginName, compilation => {
775-
compilation.fileDependencies.add(path.join(__dirname, 'contributes.json'));
776-
});
777-
},
778-
});
779-
}
793+
callback();
794+
});
780795
}
781796
}
782797

@@ -839,7 +854,7 @@ class FantasticonPlugin {
839854
}
840855

841856
const logger = compiler.getInfrastructureLogger(this.pluginName);
842-
logger.log(`Generating '${compiler.name}' icon font...`);
857+
logger.log(`[${compiler.name}] Generating icon font...`);
843858

844859
const start = Date.now();
845860

@@ -868,7 +883,7 @@ class FantasticonPlugin {
868883
})`;
869884
}
870885

871-
logger.log(`Generated '${compiler.name}' icon font in \x1b[32m${Date.now() - start}ms\x1b[0m${suffix}`);
886+
logger.log(`[${compiler.name}] Generated icon font in \x1b[32m${Date.now() - start}ms\x1b[0m${suffix}`);
872887
}
873888

874889
const generateFn = generate.bind(this);

0 commit comments

Comments
 (0)