diff --git a/.gitignore b/.gitignore index 0a8a8cc1..1655bbee 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ dist/ log.txt out node_modules -client/server \ No newline at end of file +client/server +lib +lib/ \ No newline at end of file diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 00000000..17da492c --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,6 @@ +{ + "ui": "bdd", + "color": true, + "spec": "./lib", + "recursive": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 969f17fa..fef2d96d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -27,29 +27,11 @@ "problemMatcher": ["$tsc"] }, { - "type": "shell", - "label": "Format workspace", - "command": "Powershell.exe -executionpolicy remotesigned -File ./scripts/format_documents.ps1", - "problemMatcher": "$tsc" - }, - { - "type": "shell", - "label": "build extension", - "command": "./scripts/build.bat", + "type": "npm", + "script": "test", + "isBackground": false, "group": "build", - "problemMatcher": "$tsc" - }, - { - "type": "shell", - "label": "install project extension", - "command": "Powershell.exe -executionpolicy remotesigned -File ./scripts/install.ps1", - "problemMatcher": "$tsc" - }, - { - "type": "shell", - "label": "update project extension", - "command": "Powershell.exe -executionpolicy remotesigned -File ./scripts/update.ps1", - "problemMatcher": "$tsc" + "problemMatcher": ["$tsc"] } ] } diff --git a/Minecraft bedrock json schemas.code-workspace b/Minecraft bedrock json schemas.code-workspace index d6c3860c..2a54139e 100644 --- a/Minecraft bedrock json schemas.code-workspace +++ b/Minecraft bedrock json schemas.code-workspace @@ -1,12 +1,17 @@ { - "folders": [ - { - "path": "." - } - ], - "extensions": { - "recommendations": [ - "vscode-icons-team.vscode-icons" - ] - } -} \ No newline at end of file + "folders": [{ "path": "." }], + "settings": { + "editor.formatOnSave": true, + "prettier.tabWidth": 2, + + "prettier.useTabs": false, + "prettier.printWidth": 180, + + "editor.useTabStops": false, + "editor.tabSize": 2, + + "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.useTabStops": false, "editor.tabSize": 2 }, + "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.useTabStops": false, "editor.tabSize": 2 }, + "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.useTabStops": false, "editor.tabSize": 2 } + } +} diff --git a/package-lock.json b/package-lock.json index 007e0ec8..c588c991 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "minecraft-bedrock-schemas", "version": "1.0.0", "license": "BSD-3-Clause", + "dependencies": { + "vscode-json-languageservice": "^4.1.7" + }, "devDependencies": { "@types/chai": "^4.2.21", "@types/mocha": "^9.0.0", @@ -1174,6 +1177,11 @@ "dev": true, "peer": true }, + "node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + }, "node_modules/loader-runner": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", @@ -1806,6 +1814,41 @@ "punycode": "^2.1.0" } }, + "node_modules/vscode-json-languageservice": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.7.tgz", + "integrity": "sha512-cwG5TwZyHYthsk2aS3W1dVgVP6Vwn3o+zscwN58uMgZt/nKuyxd9vdEB1F58Ix+S5kSKAnkUCP6hvulcoImQQQ==", + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + }, + "engines": { + "npm": ">=7.0.0" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", + "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "node_modules/vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==" + }, + "node_modules/vscode-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz", + "integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==" + }, "node_modules/watchpack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", @@ -3038,6 +3081,11 @@ "dev": true, "peer": true }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + }, "loader-runner": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", @@ -3471,6 +3519,38 @@ "punycode": "^2.1.0" } }, + "vscode-json-languageservice": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.7.tgz", + "integrity": "sha512-cwG5TwZyHYthsk2aS3W1dVgVP6Vwn3o+zscwN58uMgZt/nKuyxd9vdEB1F58Ix+S5kSKAnkUCP6hvulcoImQQQ==", + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", + "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==" + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==" + }, + "vscode-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz", + "integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==" + }, "watchpack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", diff --git a/package.json b/package.json index 2eb622c4..bfcdcf51 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "test": "test" }, "scripts": { - "test": "mocha -r ts-node/register '**/*.test.ts'", + "compile": "tsc -b", + "test": "mocha --debug-brk", + "pretest": "npm run compile", "update": "npm update && npm audit fix" }, "repository": { @@ -32,5 +34,8 @@ "mocha": "^9.0.3", "ts-loader": "^9.2.5", "ts-node": "^10.2.0" + }, + "dependencies": { + "vscode-json-languageservice": "^4.1.7" } } diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/test/src/SchemaTester.ts b/test/src/SchemaTester.ts index e69de29b..1e371a92 100644 --- a/test/src/SchemaTester.ts +++ b/test/src/SchemaTester.ts @@ -0,0 +1,91 @@ +import { + getLanguageService, + LanguageService, + LanguageSettings, + SchemaConfiguration, + TextDocument, + JSONDocument, + Diagnostic, + Thenable, +} from "vscode-json-languageservice"; +import * as url from "url"; +import * as data from "../../vscode-settings.json"; +import { readFileSync } from "fs"; +import { Files } from "./Utillity"; + +export namespace Schema { + const workspaceContext = { + resolveRelativePath: (relativePath: string, resource: string) => { + return url.resolve(resource, relativePath); + }, + }; + + export function GetValidator(): Validator { + const ls = GetLanguageService(); + ls.configure(GetLanguageSettings()); + + const out = new Validator(ls); + + return out; + } + + export function GetLanguageService(): LanguageService { + return getLanguageService({ workspaceContext }); + } + + export function GetLanguageSettings(): LanguageSettings { + const schemas: SchemaConfiguration[] = []; + const settings: LanguageSettings = { schemas: schemas }; + let rootfolder = Files.RootFolder(); + + if (!rootfolder.endsWith("/")) rootfolder += "/"; + + data["json.schemas"].forEach((m) => { + if (m) { + const schema = m.url.replace("https://raw.githubusercontent.com/Blockception/Minecraft-bedrock-json-schemas/main/", rootfolder); + + schemas.push({ uri: schema, fileMatch: m.fileMatch }); + } + }); + + return settings; + } +} + +export class Validator { + readonly ls: LanguageService; + + constructor(ls: LanguageService) { + this.ls = ls; + } + + ValidateFile(uri: string): Result { + const content = readFileSync(uri).toString(); + return this.ValidateContent(content, uri, "json"); + } + + ValidateJson(data: any, fakeuri: string = "", langid: string = "json"): Result { + return this.ValidateContent(JSON.stringify(data), fakeuri, langid); + } + + ValidateContent(json: string, fakeuri: string = "", langid: string = "json"): Result { + const doc = TextDocument.create(fakeuri, langid, 0, json); + const jdoc = this.ls.parseJSONDocument(doc); + + const p = this.ls.doValidation(doc, jdoc, { comments: "ignore" }); + + return new Result(doc, jdoc, p); + } +} + +export class Result { + readonly doc: TextDocument; + readonly jdoc: JSONDocument; + readonly promise: Thenable; + + constructor(doc: TextDocument, jdoc: JSONDocument, promise: Thenable) { + this.doc = doc; + this.jdoc = jdoc; + this.promise = promise; + } +} diff --git a/test/src/Utillity.test.ts b/test/src/Utillity.test.ts new file mode 100644 index 00000000..3e21da8a --- /dev/null +++ b/test/src/Utillity.test.ts @@ -0,0 +1,20 @@ +import { expect } from "chai"; +import { Files } from "./Utillity"; + +describe("files", () => { + it("Root", () => { + const temp = Files.RootFolder(); + console.log(temp); + + expect(temp.endsWith("lib"), "ended with lib").to.be.false; + expect(temp.endsWith("lib\\test"), "ended with lib\\test").to.be.false; + expect(temp.endsWith("lib/test"), "ended with lib/test").to.be.false; + }); + + it("Test", () => { + const temp = Files.TestFolder(); + console.log(temp); + + expect(temp.endsWith("lib"), "ended with lib").to.be.false; + }); +}); diff --git a/test/src/Utillity.ts b/test/src/Utillity.ts index 02152279..ca479bef 100644 --- a/test/src/Utillity.ts +++ b/test/src/Utillity.ts @@ -1,11 +1,28 @@ -import path from "path"; +import FastGlob = require("fast-glob"); +import path = require("path"); export namespace Files { - export function TestFolder(): string { - return __dirname; - } + export function TestFolder(): string { + return path.join(__dirname, "..", "..", "test"); + } - export function FilesFolder(): string { - return path.join(TestFolder(), "files"); - } + export function RootFolder(): string { + return path.join(TestFolder(), ".."); + } + + export function FilesFolder(): string { + return path.join(TestFolder(), "files"); + } + + export function CorrectFilesFolder(): string { + return path.join(FilesFolder(), "correct"); + } + + export function InCorrectFilesFolder(): string { + return path.join(FilesFolder(), "incorrect"); + } + + export function GetFiles(folder: string): string[] { + return FastGlob.sync(folder, { absolute: true, onlyFiles: true }); + } } diff --git a/test/src/files/validate.test.ts b/test/src/files/validate.test.ts new file mode 100644 index 00000000..7560259a --- /dev/null +++ b/test/src/files/validate.test.ts @@ -0,0 +1,30 @@ +import { expect } from "chai"; +import { Schema } from "../SchemaTester"; +import { Files } from "../Utillity"; + +describe("test correct files", () => { + const folder = Files.CorrectFilesFolder(); + const files = Files.GetFiles(folder); + const validator = Schema.GetValidator(); + + files.forEach((file) => { + if (file.endsWith(".json")) { + const testfolder = file.replace(folder, ""); + + test(testfolder, (done) => { + let result = validator.ValidateFile(file); + + result.promise.then( + (succes) => { + expect(succes.length, "Expected no errors got: " + JSON.stringify(succes)).to.equal(0); + done(); + }, + (fail) => { + expect.fail("Failed to validate"); + done(); + } + ); + }); + } + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..4c2537b0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "include": ["src", "test"], + "exclude": ["node_modules", "**/__tests__/*"], + "compilerOptions": { + "target": "es2019", + "module": "commonjs", + "declaration": true, + "outDir": "./lib", + "strict": true, + "resolveJsonModule": true, + "sourceMap": true + } +}