118 lines
3.9 KiB
JavaScript
118 lines
3.9 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { spawnSync } from 'node:child_process';
|
|
import { createRequire } from 'node:module';
|
|
import { existsSync, readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
|
|
const args = process.argv.slice(2);
|
|
const includeLint = args.includes('--lint');
|
|
const positional = args.filter(arg => !arg.startsWith('--'));
|
|
const root = resolve(positional[0] ?? process.cwd());
|
|
const require = createRequire(import.meta.url);
|
|
|
|
function fail(message) {
|
|
throw new Error(message);
|
|
}
|
|
|
|
function readJson(relativePath) {
|
|
const absolutePath = resolve(root, relativePath);
|
|
if (!existsSync(absolutePath)) {
|
|
fail(`Missing ${relativePath}`);
|
|
}
|
|
try {
|
|
return JSON.parse(readFileSync(absolutePath, 'utf8'));
|
|
} catch (error) {
|
|
fail(`Invalid JSON in ${relativePath}: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
function runNpm(script) {
|
|
const windows = process.platform === 'win32';
|
|
const command = windows ? (process.env.ComSpec ?? 'cmd.exe') : 'npm';
|
|
const commandArgs = windows ? ['/d', '/s', '/c', `npm run ${script}`] : ['run', script];
|
|
const result = spawnSync(command, commandArgs, {
|
|
cwd: root,
|
|
stdio: 'inherit'
|
|
});
|
|
if (result.error) {
|
|
fail(`Could not run npm script ${script}: ${result.error.message}`);
|
|
}
|
|
if (result.status !== 0) {
|
|
fail(`npm run ${script} exited with ${result.status}`);
|
|
}
|
|
}
|
|
|
|
function assertContributionPaths(packageJson) {
|
|
const paths = [packageJson.main];
|
|
for (const language of packageJson.contributes?.languages ?? []) {
|
|
paths.push(language.configuration);
|
|
}
|
|
for (const grammar of packageJson.contributes?.grammars ?? []) {
|
|
paths.push(grammar.path);
|
|
}
|
|
for (const snippet of packageJson.contributes?.snippets ?? []) {
|
|
paths.push(snippet.path);
|
|
}
|
|
for (const relativePath of paths.filter(Boolean)) {
|
|
if (!existsSync(resolve(root, relativePath))) {
|
|
fail(`package.json references missing path ${relativePath}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function smokeTestCore() {
|
|
const tokenizerPath = resolve(root, 'out/tokenizer.js');
|
|
const parserPath = resolve(root, 'out/parser.js');
|
|
if (!existsSync(tokenizerPath) || !existsSync(parserPath)) {
|
|
fail('Compiled tokenizer/parser output is missing');
|
|
}
|
|
|
|
const { EftlTokenizer } = require(tokenizerPath);
|
|
const { EftlParser } = require(parserPath);
|
|
const sample = readFileSync(resolve(root, 'examples/sample.eftl'), 'utf8');
|
|
const sampleResult = new EftlTokenizer(sample).tokenize();
|
|
const sampleParse = new EftlParser(sampleResult.tokens).parse();
|
|
if (sampleResult.errors.length || sampleParse.errors.length) {
|
|
fail(`sample.eftl is not accepted: ${sampleResult.errors.length} tokenizer and ${sampleParse.errors.length} parser errors`);
|
|
}
|
|
|
|
const mismatched = new EftlTokenizer('[EFTL][IF][/EFTL]').tokenize();
|
|
if (new EftlParser(mismatched.tokens).parse().errors.length === 0) {
|
|
fail('Parser smoke case did not reject mismatched nesting');
|
|
}
|
|
|
|
const comment = new EftlTokenizer('[EFTL][!-- unfinished').tokenize();
|
|
if (comment.errors.length === 0) {
|
|
fail('Tokenizer smoke case did not reject an unterminated comment');
|
|
}
|
|
}
|
|
|
|
try {
|
|
const packageJson = readJson('package.json');
|
|
readJson('language-configuration.json');
|
|
readJson('syntaxes/eftl.tmLanguage.json');
|
|
readJson('snippets/eftl.json');
|
|
|
|
runNpm('compile');
|
|
assertContributionPaths(packageJson);
|
|
smokeTestCore();
|
|
|
|
if (packageJson.scripts?.test) {
|
|
runNpm('test');
|
|
} else {
|
|
console.warn('WARN: package.json has no test script; only smoke cases were run.');
|
|
}
|
|
|
|
if (includeLint) {
|
|
runNpm('lint');
|
|
} else if (packageJson.scripts?.lint) {
|
|
console.warn('WARN: lint was skipped; pass --lint after configuring ESLint.');
|
|
}
|
|
|
|
console.log('EFTL repository baseline checks passed.');
|
|
} catch (error) {
|
|
console.error(`FAIL: ${error.message}`);
|
|
process.exitCode = 1;
|
|
}
|