"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.");