generator-code
Version:
Yeoman generator for Visual Studio Code Extensions
130 lines (113 loc) • 3.62 kB
text/typescript
// This script checks that the test provider isn't included in the package.json
// or extension.ts. The extension provider is given as a tool for development,
// but should not be published to the marketplace.
//
// This script is not super comprehensive, it's just here to prevent simple mistakes.
import * as ts from 'typescript';
import * as path from 'path';
import { readFileSync, existsSync, writeFileSync } from 'fs';
import { EOL } from 'os';
const rootDir = path.resolve(__dirname, '..', '..');
const packageJson = require('../../package.json');
class DetectedError extends Error {
constructor(message: string, public readonly fix: () => void) {
super(message);
}
}
const checkNotInExtensionTs = () => {
const entrypoint = path.resolve(rootDir, 'src', 'extension', 'extension.ts');
if (!existsSync(entrypoint)) {
return;
}
const contents = readFileSync(entrypoint, 'utf-8');
const program = ts.createSourceFile(
path.basename(entrypoint),
contents,
ts.ScriptTarget.ESNext,
true,
);
const removeRegistration = (node: ts.Node) => () => writeFileSync(
entrypoint,
contents.slice(0, node.pos) + contents.slice(node.end + +(contents[node.end] === ',')),
);
ts.forEachChild(program, function walk(node: ts.Node) {
if (
ts.isCallExpression(node) &&
/(^|\W)registerNotebookContentProvider$/.test(node.expression.getText()) &&
node.arguments[1]?.getText().includes('TestProvider')
) {
throw new DetectedError(
'`registerNotebookContentProvider()` is still called with the TestProvider.',
removeRegistration(node),
);
}
if (
ts.isCallExpression(node) &&
/(^|\W)registerNotebookKernel$/.test(node.expression.getText()) &&
node.arguments[2]?.getText().includes('TestKernel')
) {
throw new DetectedError(
'`registerNotebookKernel()` is still called with the TestKernel.',
removeRegistration(node),
);
}
ts.forEachChild(node, walk);
});
};
const checkNotInPackageJson = () => {
const providers = packageJson.contributes?.notebookProvider ?? [];
const testIndex = providers.findIndex(
(p: { viewType: string }) => p.viewType === 'test-notebook-renderer',
);
if (testIndex !== -1) {
throw new DetectedError(
`The "test-notebook-renderer" is still registered in the contributes section of your package.json.`,
() => {
providers.splice(testIndex, 1);
writeFileSync(
path.resolve(rootDir, 'package.json'),
JSON.stringify(packageJson, null, 2) + EOL,
);
},
);
}
};
(() => {
if (process.argv.includes('--fix')) {
while (true) {
try {
checkNotInPackageJson();
checkNotInExtensionTs();
} catch (e) {
if (!(e instanceof DetectedError)) {
throw e;
} else {
e.fix();
continue;
}
}
return console.log('Test provider removed!');
}
}
let errors: DetectedError[] = [];
for (const check of [checkNotInPackageJson, checkNotInExtensionTs]) {
try {
check();
} catch (e) {
if (!(e instanceof DetectedError)) {
throw e;
}
errors.push(e);
}
}
if (!errors.length) {
return;
}
const execPath = path.relative(process.cwd(), __filename);
console.error(errors.map((e) => e.message).join(' '));
console.error('');
console.error(
'You should remove the test provider before publishing your extension to avoid ' +
`conflicts. To fix this automatically, run \`node ${execPath} --fix\``,
);
})();