diff --git a/client/src/extension.ts b/client/src/extension.ts index 0b4313a..98590f0 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode' import * as vscodeLang from 'vscode-languageclient' import * as path from 'path' -export function activate(context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext) { const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js')) const debugOpts = { execArgv: ['--nolazy', '--inspect=6009']} @@ -27,4 +27,10 @@ export function activate(context: vscode.ExtensionContext) { const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts) context.subscriptions.push(langServer.start()) + + await langServer.onReady() + + langServer.onNotification('update-config', (dir: string) => { + vscode.workspace.getConfiguration().update('mcglsl.glslangValidatorPath', dir, vscode.ConfigurationTarget.Global) + }) } \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json index 9055cd2..9b2beea 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,9 +1,256 @@ { "name": "vscode-mc-shader-server", - "version": "0.0.1", + "version": "0.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/node": { + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", + "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==" + }, + "@types/node-fetch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.1.1.tgz", + "integrity": "sha512-IfDil0fSMq59n4UsIzgRd5gsgmgn9dl9PzZbguKPsGBpLEIFC7Fr4AroQjIeCYOcDsP1Lszm10wirpaEP26Lhg==", + "requires": { + "@types/node": "*" + } + }, + "@types/unzip": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@types/unzip/-/unzip-0.1.1.tgz", + "integrity": "sha512-skD6Um7Pk2l7y+tVOKSgOA9vXViyhk/qJYmr17Ek4Uw3Zgo/DWPScphTPztPbApTIngyYSJnkEW87xrHzRYaew==", + "requires": { + "@types/node": "*" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", + "requires": { + "graceful-fs": "~3.0.2", + "inherits": "~2.0.0", + "mkdirp": "0.5", + "rimraf": "2" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "requires": { + "natives": "^1.1.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "requires": { + "buffers": "~0.1.1", + "readable-stream": "~1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "natives": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==" + }, + "node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "over": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "requires": { + "over": ">= 0.0.5 < 1", + "readable-stream": "~1.0.31", + "setimmediate": ">= 1.0.2 < 2", + "slice-stream": ">= 1.0.0 < 2" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "requires": { + "readable-stream": "~1.0.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + }, + "unzip": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", + "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", + "requires": { + "binary": ">= 0.3.0 < 1", + "fstream": ">= 0.1.30 < 1", + "match-stream": ">= 0.0.2 < 1", + "pullstream": ">= 0.4.1 < 1", + "readable-stream": "~1.0.31", + "setimmediate": ">= 1.0.1 < 2" + } + }, "vscode-jsonrpc": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz", @@ -36,6 +283,11 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.3.tgz", "integrity": "sha1-Yxvb9xbcyrDmUpGo3CXCMjIIWlI=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } diff --git a/server/package.json b/server/package.json index 7bb32b0..a84fa35 100644 --- a/server/package.json +++ b/server/package.json @@ -12,6 +12,10 @@ "node": "*" }, "dependencies": { + "@types/node-fetch": "^2.1.1", + "@types/unzip": "^0.1.1", + "node-fetch": "^2.1.2", + "unzip": "^0.1.11", "vscode-languageserver": "^4.1.3" }, "scripts": { diff --git a/server/src/config.ts b/server/src/config.ts index be19647..22bd034 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -1,9 +1,71 @@ -export class Config { - public readonly shaderpacksPath: string - public readonly glslangPath: string +import { connection, documents, onEvent } from './server' +import { exec, execSync } from 'child_process' +import { extname } from 'path' +import fetch from 'node-fetch' +import { platform } from 'os' +import { createWriteStream, chmodSync, createReadStream, unlinkSync } from 'fs' +import * as unzip from 'unzip' - constructor(shaderpacksPath: string, glslangPath: string) { - this.shaderpacksPath = shaderpacksPath - this.glslangPath = glslangPath || 'glslangValidator' +const url = { + 'win32': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-windows-x64-Release.zip', + 'linux': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-linux-Release.zip', + 'darwin': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-osx-Release.zip' +} + +export interface Config { + readonly shaderpacksPath: string + readonly glslangPath: string +} + +export let conf: Partial = {} + +connection.onDidChangeConfiguration(async (change) => { + const temp = change.settings.mcglsl as Config + conf = {shaderpacksPath: temp['shaderpacksPath'], glslangPath: temp['glslangValidatorPath']} + try { + execSync(conf.glslangPath) + documents.all().forEach(document => onEvent) + } catch (e) { + if (e.status !== 1) { + const chosen = await connection.window.showErrorMessage( + `[mc-glsl] glslangValidator not found at: '${conf.glslangPath}' or returned non-0 code`, + {title: 'Download'}, + {title: 'Cancel'} + ) + + if (!chosen || chosen.title !== 'Download') return + + if (conf.shaderpacksPath === '') { + connection.window.showErrorMessage('Please set mcglsl.shaderpacksPath') + return + } + + const res = await fetch(url[platform()]) + + try { + const zip = createWriteStream(conf.shaderpacksPath + '/glslangValidator.zip') + res.body.pipe(zip) + + zip.on('finish', async () => { + createReadStream(conf.shaderpacksPath + '/glslangValidator.zip') + .pipe(unzip.Parse()) + .on('entry', (entry) => { + if (entry.path === 'bin/glslangValidator') { + entry.pipe(createWriteStream(conf.shaderpacksPath + '/glslangValidator')) + return + } + entry.autodrain() + }) + .on('close', () => { + chmodSync(conf.shaderpacksPath + '/glslangValidator', 0o775) + unlinkSync(conf.shaderpacksPath + '/glslangValidator.zip') + connection.sendNotification('update-config', conf.shaderpacksPath + '/glslangValidator') + connection.window.showInformationMessage('glslangValidator has been downloaded to ' + conf.shaderpacksPath + '/glslangValidator') + }) + }) + } catch (e) { + connection.window.showErrorMessage(e.message) + } + } } -} \ No newline at end of file +}) \ No newline at end of file diff --git a/server/src/linter.ts b/server/src/linter.ts index a7dea21..61ebb30 100644 --- a/server/src/linter.ts +++ b/server/src/linter.ts @@ -1,8 +1,9 @@ import { TextDocument, Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver' -import { conf, connection, documents } from './server' +import { connection, documents } from './server' import { execSync } from 'child_process' import * as path from 'path' import { readFileSync } from 'fs' +import { conf } from './config' const reDiag = /^(ERROR|WARNING): ([^?<>:*|"]+?):(\d+): (?:'.*?' : )?(.+)$/ const reVersion = /#version [\d]{3}/ @@ -102,6 +103,7 @@ function processIncludes(lines: string[], incStack: string[]) { function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[]) { const incPath = absPath(inc.parent, inc.match[1]) + console.log(incPath) if (!incPath) return false const dataLines = readFileSync(incPath).toString().split('\n') incStack.push(incPath) diff --git a/server/src/server.ts b/server/src/server.ts index 1b70a79..589c0e6 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -5,14 +5,16 @@ import { completions } from './completionProvider' import { preprocess, ext, formatURI } from './linter' import { exec, execSync } from 'child_process' import { extname } from 'path' +import fetch from 'node-fetch' +import { platform } from 'os' +import { createWriteStream, chmodSync, createReadStream, unlinkSync } from 'fs' +import * as unzip from 'unzip' export const connection = vsclang.createConnection(new vsclang.IPCMessageReader(process), new vsclang.IPCMessageWriter(process)) export const documents = new vsclang.TextDocuments() documents.listen(connection) -export let conf = new Config('', '') - connection.onInitialize((params): vsclang.InitializeResult => { return { capabilities: { @@ -32,7 +34,7 @@ documents.onDidSave((event) => onEvent(event.document)) //documents.onDidChangeContent(onEvent) -function onEvent(document: vsclangproto.TextDocument) { +export function onEvent(document: vsclangproto.TextDocument) { if (!ext.has(extname(document.uri))) return try { preprocess(document.getText().split('\n'), formatURI(document.uri)) @@ -41,24 +43,6 @@ function onEvent(document: vsclangproto.TextDocument) { } } -connection.onDidChangeConfiguration(async (change) => { - const temp = change.settings.mcglsl as Config - conf = new Config(temp['shaderpacksPath'], temp['glslangValidatorPath']) - try { - execSync(conf.glslangPath) - documents.all().forEach(document => onEvent) - } catch (e) { - if (e.status !== 1) { - const chosen = await connection.window.showErrorMessage( - `[mc-glsl] glslangValidator not found at: '${conf.glslangPath}' or returned non-0 code`, - {title: 'Download'}, - {title: 'Cancel'} - ) - console.log(chosen.title) - } - } -}) - connection.onCompletion((textDocumentPosition: vsclang.TextDocumentPositionParams) => completions) connection.onCompletionResolve((item: vsclang.CompletionItem): vsclang.CompletionItem => completions[item.data - 1]) diff --git a/setup.py b/setup.py index 48e2ad3..1ea6591 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,6 @@ import urllib.request import zipfile from io import BytesIO -import shutil import os as o os = { @@ -31,4 +30,5 @@ def main(): print('glslangValidator downloaded. Add this line to your VSCode settings:\n"mcglsl.glslangValidatorPath": "' + o.getcwd() + '/' + 'glslangValidator"') return print('There was an error :(') + main() \ No newline at end of file