gotlin/tools/vscode-gotlin/scripts/validate.js

90 lines
3.6 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const root = path.resolve(__dirname, "..");
function readJSON(relativePath) {
return JSON.parse(fs.readFileSync(path.join(root, relativePath), "utf8"));
}
const packageJSON = readJSON("package.json");
const language = readJSON("language-configuration.json");
const grammar = readJSON("syntaxes/gotlin.tmLanguage.json");
const snippets = readJSON("snippets/gotlin.code-snippets");
function validateRegexes(value) {
if (Array.isArray(value)) {
value.forEach(validateRegexes);
return;
}
if (!value || typeof value !== "object") {
return;
}
for (const [key, child] of Object.entries(value)) {
if (["match", "begin", "end"].includes(key)) {
assert.doesNotThrow(() => new RegExp(child), `invalid ${key} regex: ${child}`);
} else {
validateRegexes(child);
}
}
}
validateRegexes(grammar);
assert.equal(packageJSON.version, "0.1.0");
assert(packageJSON.activationEvents.includes("onLanguage:gotlin"));
assert.equal(packageJSON.contributes.grammars[0].scopeName, "source.gotlin");
assert(language.brackets.some(([open, close]) => open === "[" && close === "]"));
assert(language.folding?.markers?.start && language.indentationRules?.increaseIndentPattern);
const grammarSource = JSON.stringify(grammar);
const expectedTokens = [
"data", "class", "worker", "private", "override", "val", "var", "if", "else",
"while", "for", "in", "select", "return", "go", "defer", "try", "catch",
"throw", "enum", "match", "package", "import", "jsonNaming", "embed", "table", "column", "id",
"generated", "Int", "String", "Boolean", "Unit", "Double", "Float", "Any",
"ByteSlice", "List", "MutableList", "Map", "MutableMap", "Channel", "GotlinSQLQuery",
"GotlinSQLIterator", "from", "where", "orderBy", "orderByDescending", "limit",
"forUpdate", "skipLocked", "insert", "update", "delete", "onConflict", "doNothing",
"doUpdate", "returning", "build", "fetch", "single", "iterator", "set", "now", "mapTo"
];
for (const token of expectedTokens) {
assert(grammarSource.includes(token), `grammar is missing ${token}`);
}
const annotationSource = JSON.stringify(grammar.repository.annotations);
for (const annotation of ["jsonNaming", "embed", "table", "column", "id", "generated"]) {
assert(annotationSource.includes(annotation), `annotation grammar is missing ${annotation}`);
}
const sqlSource = JSON.stringify(grammar.repository.sql);
for (const method of [
"from", "where", "select", "orderBy", "orderByDescending", "limit", "forUpdate",
"skipLocked", "insert", "update", "delete", "onConflict", "doNothing", "doUpdate",
"returning", "build", "fetch", "single", "iterator", "set", "now"
]) {
assert(sqlSource.includes(method), `SQL grammar is missing ${method}`);
}
const imports = grammar.repository.imports.patterns.map((pattern) => new RegExp(pattern.match));
for (const declaration of [
"import encoding.json",
"import json encoding.json",
"import pgxpool \"github.com/jackc/pgx/v5/pgxpool\"",
"import \"example.com/module/package\""
]) {
assert(imports.some((pattern) => pattern.test(declaration)), `import grammar rejected: ${declaration}`);
}
const prefixes = new Set(Object.values(snippets).map((snippet) => snippet.prefix));
for (const prefix of [
"dataclass", "tablerow", "embed", "worker", "enum", "match", "mapto", "go", "defer", "foreach", "sqlfetch",
"sqlsingle", "sqliterator", "sqlinsertnothing", "sqlinsertupdate", "sqlupdatereturning"
]) {
assert(prefixes.has(prefix), `snippets are missing prefix ${prefix}`);
}
console.log("Validated Gotlin package metadata, grammar, language configuration, and snippets.");