Moved to vscode provided global file storage path to DL glslangValidator

This commit is contained in:
Noah Santschi-Cooney 2020-07-18 23:11:26 +01:00
parent 39143aefc7
commit f7310c1573
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
11 changed files with 62 additions and 150 deletions

6
.vscode/launch.json vendored
View file

@ -14,11 +14,5 @@
"script": "watch" "script": "watch"
} }
} }
],
"compounds": [
{
"name": "Client + Server",
"configurations": ["Launch Client", "Attach to Server"]
}
] ]
} }

13
.vscode/settings.json vendored
View file

@ -1,16 +1,3 @@
/*
👋 Hi! This file was autogenerated by tslint-to-eslint-config.
https://github.com/typescript-eslint/tslint-to-eslint-config
It represents the closest reasonable ESLint configuration to this
project's original TSLint configuration.
We recommend eventually switching this configuration to extend from
the recommended rulesets in typescript-eslint.
https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md
Happy linting! 💖
*/
{ {
"files.exclude": { "files.exclude": {
"out": false "out": false

View file

@ -1,23 +1,20 @@
import * as vscode from 'vscode' import * as vscode from 'vscode'
import * as lsp from 'vscode-languageclient' import * as lsp from 'vscode-languageclient'
import * as commands from './commands' import * as commands from './commands'
import { promptDownload, testExecutable } from './glslangValidator' import { bootstrapGLSLangValidator } from './glslangValidator'
import { log } from './log' import { log } from './log'
import { LanguageClient } from './lspClient' import { LanguageClient } from './lspClient'
export const glslConfigParam = 'mcglsl.glslangValidatorPath'
export let statusBarItem: vscode.StatusBarItem | null = null
export class Extension { export class Extension {
private statusBarItem: vscode.StatusBarItem | null = null
private extensionContext: vscode.ExtensionContext | null = null private extensionContext: vscode.ExtensionContext | null = null
private client: lsp.LanguageClient private client: lsp.LanguageClient
public get context() : vscode.ExtensionContext { public get context(): vscode.ExtensionContext {
return this.extensionContext return this.extensionContext
} }
public get lspClient() : lsp.LanguageClient { public get lspClient(): lsp.LanguageClient {
return this.client return this.client
} }
@ -27,16 +24,13 @@ export class Extension {
this.registerCommand('graphDot', commands.generateGraphDot) this.registerCommand('graphDot', commands.generateGraphDot)
this.registerCommand('restart', commands.restartExtension) this.registerCommand('restart', commands.restartExtension)
if (!testExecutable(vscode.workspace.getConfiguration().get(glslConfigParam) as string)) { if(!await bootstrapGLSLangValidator(this)) return
if(!await promptDownload(this)) return
}
log.info('starting language server...') log.info('starting language server...')
this.client = await new LanguageClient(this).startServer() this.client = await new LanguageClient(this).startServer()
log.info('language server started!') log.info('language server started!')
} }
registerCommand = (name: string, f: (e: Extension) => commands.Command) => { registerCommand = (name: string, f: (e: Extension) => commands.Command) => {
@ -52,17 +46,16 @@ export class Extension {
} }
public updateStatus = (icon: string, text: string) => { public updateStatus = (icon: string, text: string) => {
statusBarItem?.dispose() this.statusBarItem?.dispose()
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left) this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left)
statusBarItem.text = icon + ' [mc-shader] ' + text this.statusBarItem.text = icon + ' [mc-shader] ' + text
statusBarItem.show() this.statusBarItem.show()
this.context.subscriptions.push(statusBarItem) this.context.subscriptions.push(this.statusBarItem)
} }
public clearStatus = () => { public clearStatus = () => {
statusBarItem?.dispose() this.statusBarItem?.dispose()
} }
} }
export const activate = new Extension().activate export const activate = new Extension().activate

View file

@ -1,10 +1,11 @@
import * as unzip from 'adm-zip' import * as unzip from 'adm-zip'
import { execSync } from 'child_process' import { execSync } from 'child_process'
import * as fs from 'fs'
import { writeFileSync } from 'fs' import { writeFileSync } from 'fs'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { platform } from 'os' import { platform } from 'os'
import * as vscode from 'vscode' import * as vscode from 'vscode'
import { Extension, glslConfigParam } from './extension' import { Extension } from './extension'
import { log } from './log' import { log } from './log'
const url = { const url = {
@ -15,9 +16,17 @@ const url = {
const config = vscode.workspace.getConfiguration() const config = vscode.workspace.getConfiguration()
export async function promptDownload(e: Extension): Promise<boolean> { export async function bootstrapGLSLangValidator(e: Extension): Promise<boolean> {
const glslangValidatorPath = config.get('mcglsl.glslangValidatorPath') as string
if (!testExecutable(glslangValidatorPath)) {
if(!await promptDownload(e, glslangValidatorPath)) return false
}
return true
}
async function promptDownload(e: Extension, glslangValidatorPath: string): Promise<boolean> {
const chosen = await vscode.window.showErrorMessage( const chosen = await vscode.window.showErrorMessage(
`[mc-glsl] glslangValidator not found at: '${config.get(glslConfigParam)}'.`, `[mc-glsl] glslangValidator not found at: '${glslangValidatorPath}'.`,
{title: 'Download'}, {title: 'Download'},
{title: 'Cancel'} {title: 'Cancel'}
) )
@ -40,10 +49,12 @@ async function tryInstallExecutable(e: Extension): Promise<boolean> {
} }
async function installExecutable(e: Extension) { async function installExecutable(e: Extension) {
fs.mkdirSync(e.context.globalStoragePath, { recursive: true })
e.updateStatus('$(cloud-download)', 'Downloading glslangValidator') e.updateStatus('$(cloud-download)', 'Downloading glslangValidator')
const glslangBin = '/glslangValidator' + (platform() === 'win32' ? '.exe' : '') const glslangBin = '/glslangValidator' + (platform() === 'win32' ? '.exe' : '')
const glslangPath = config.get('mcglsl.shaderpacksPath') + glslangBin const glslangPath = e.context.globalStoragePath + glslangBin
const response = await fetch(url[platform()]) const response = await fetch(url[platform()])
log.info('glslangValidator download response status: ' + response.status) log.info('glslangValidator download response status: ' + response.status)
@ -64,12 +75,11 @@ async function installExecutable(e: Extension) {
vscode.window.showInformationMessage( vscode.window.showInformationMessage(
`glslangValidator has been downloaded to ${glslangPath}. Your config should be updated automatically.` `glslangValidator has been downloaded to ${glslangPath}. Your config should be updated automatically.`
) )
config.update('mcglsl.glslangValidatorPath', glslangPath, vscode.ConfigurationTarget.Global) await config.update('mcglsl.glslangValidatorPath', glslangPath, vscode.ConfigurationTarget.Global)
e.clearStatus() e.clearStatus()
} }
export function testExecutable(glslangPath?: string): boolean { function testExecutable(glslangPath: string): boolean {
glslangPath = glslangPath || config.get(glslConfigParam)
let stdout = '' let stdout = ''
try { try {
stdout = execSync(glslangPath, { stdout = execSync(glslangPath, {

View file

@ -1,5 +1,7 @@
import { inspect } from 'util' import { inspect } from 'util';
import * as vscode from 'vscode' import * as vscode from 'vscode';
export const lspOutputChannel = vscode.window.createOutputChannel('Minecraft Shaders Language Server')
// from rust-analyzer https://github.com/rust-analyzer/rust-analyzer/blob/ef223b9e6439c228e0be49861efd2067c0b22af4/editors/code/src/util.ts // from rust-analyzer https://github.com/rust-analyzer/rust-analyzer/blob/ef223b9e6439c228e0be49861efd2067c0b22af4/editors/code/src/util.ts
export const log = new class { export const log = new class {
@ -37,30 +39,3 @@ export const log = new class {
} }
} }
export const lspExceptionLogger = new class implements vscode.OutputChannel {
name: string
append(value: string): void {
log.write('LSP-F', value)
}
appendLine(value: string): void {
log.write('LSP-F', value)
}
clear(): void {
log.output.clear()
}
show(column?: any, preserveFocus?: any) {
log.output.show(column, preserveFocus)
}
hide(): void {
log.output.hide()
}
dispose(): void {
log.output.dispose()
}
}

View file

@ -2,7 +2,7 @@ import * as path from 'path'
import { ConfigurationTarget, workspace } from 'vscode' import { ConfigurationTarget, workspace } from 'vscode'
import * as lsp from 'vscode-languageclient' import * as lsp from 'vscode-languageclient'
import { Extension } from './extension' import { Extension } from './extension'
import { lspExceptionLogger } from './log' import { lspOutputChannel } from './log'
import { ConfigUpdateParams, statusMethod, StatusParams, updateConfigMethod } from './lspExt' import { ConfigUpdateParams, statusMethod, StatusParams, updateConfigMethod } from './lspExt'
export class LanguageClient extends lsp.LanguageClient { export class LanguageClient extends lsp.LanguageClient {
@ -13,7 +13,7 @@ export class LanguageClient extends lsp.LanguageClient {
command: ext.context.asAbsolutePath(path.join('server', 'target', 'debug', 'vscode-mc-shader')), command: ext.context.asAbsolutePath(path.join('server', 'target', 'debug', 'vscode-mc-shader')),
}, { }, {
documentSelector: [{scheme: 'file', language: 'glsl'}], documentSelector: [{scheme: 'file', language: 'glsl'}],
outputChannel: lspExceptionLogger, outputChannel: lspOutputChannel,
synchronize: { synchronize: {
configurationSection: 'mcglsl', configurationSection: 'mcglsl',
fileEvents: workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}') fileEvents: workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}')

View file

@ -56,7 +56,7 @@
} }
], ],
"configuration": { "configuration": {
"title": "Minecraft GLSL configurations", "title": "Minecraft GLSL Shaders",
"properties": { "properties": {
"mcglsl.glslangValidatorPath": { "mcglsl.glslangValidatorPath": {
"type": "string", "type": "string",

View file

@ -104,11 +104,6 @@ impl Configuration {
} }
} }
struct GLSLFile {
idx: petgraph::graph::NodeIndex,
includes: Vec<IncludePosition>,
}
#[derive(Clone)] #[derive(Clone)]
pub struct IncludePosition { pub struct IncludePosition {
filepath: String, filepath: String,
@ -136,7 +131,7 @@ impl MinecraftShaderLanguageServer {
pub fn gen_initial_graph(&self, root: &str) { pub fn gen_initial_graph(&self, root: &str) {
let mut files = HashMap::new(); let mut files = HashMap::new();
eprint!("root of project is {}", root); eprintln!("root of project is {}", root);
// filter directories and files not ending in any of the 3 extensions // filter directories and files not ending in any of the 3 extensions
let file_iter = walkdir::WalkDir::new(root) let file_iter = walkdir::WalkDir::new(root)
@ -155,7 +150,7 @@ impl MinecraftShaderLanguageServer {
let ext = match path.extension() { let ext = match path.extension() {
Some(e) => e, Some(e) => e,
None => { None => {
eprint!("filepath {} had no extension", path.to_str().unwrap()); eprintln!("filepath {} had no extension", path.to_str().unwrap());
return None; return None;
} }
}; };
@ -172,21 +167,24 @@ impl MinecraftShaderLanguageServer {
let idx = self.graph.borrow_mut().add_node(path.clone()); let idx = self.graph.borrow_mut().add_node(path.clone());
//eprint!("adding {} with\n{:?}", path.clone(), includes); //eprintln!("adding {} with\n{:?}", path.clone(), includes);
struct GLSLFile {
idx: petgraph::graph::NodeIndex,
includes: Vec<IncludePosition>,
}
files.insert(path, GLSLFile { idx, includes }); files.insert(path, GLSLFile { idx, includes });
} }
// Add edges between nodes, finding target nodes on weight (value) // Add edges between nodes, finding target nodes on weight (value)
for (_, v) in files.into_iter() { for (_, v) in files.into_iter() {
for file in v.includes { for file in v.includes {
//eprint!("searching for {}", file); //eprintln!("searching for {}", file);
let idx = self.graph.borrow_mut().find_node(file.filepath.as_str()); let idx = self.graph.borrow_mut().find_node(file.filepath.as_str());
if idx.is_none() { if idx.is_none() {
eprint!("couldn't find {} in graph for {}", file, self.graph.borrow().graph[v.idx]); eprintln!("couldn't find {} in graph for {}", file, self.graph.borrow().graph[v.idx]);
continue; continue;
} }
//eprint!("added edge between\n\t{}\n\t{}", k, file); //eprintln!("added edge between\n\t{}\n\t{}", k, file);
self.graph.borrow_mut().add_edge( self.graph.borrow_mut().add_edge(
v.idx, v.idx,
idx.unwrap(), idx.unwrap(),
@ -198,7 +196,7 @@ impl MinecraftShaderLanguageServer {
} }
} }
eprint!("finished building project include graph"); eprintln!("finished building project include graph");
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_secs(1));
} }
@ -219,7 +217,7 @@ impl MinecraftShaderLanguageServer {
.unwrap() .unwrap()
.get(1) .get(1)
.unwrap(); .unwrap();
//eprint!("{:?}", caps); //eprintln!("{:?}", caps);
let start = u64::try_from(cap.start()).unwrap(); let start = u64::try_from(cap.start()).unwrap();
let end = u64::try_from(cap.end()).unwrap(); let end = u64::try_from(cap.end()).unwrap();
@ -234,7 +232,7 @@ impl MinecraftShaderLanguageServer {
start, start,
end, end,
}); });
//eprint!("{} includes {}", file, full_include); //eprintln!("{} includes {}", file, full_include);
}); });
return includes; return includes;
@ -242,7 +240,7 @@ impl MinecraftShaderLanguageServer {
pub fn lint(&self, source: impl Into<String>) -> Vec<Diagnostic> { pub fn lint(&self, source: impl Into<String>) -> Vec<Diagnostic> {
let source: String = source.into(); let source: String = source.into();
eprint!("validator bin path: {}", self.config.glslang_validator_path); eprintln!("validator bin path: {}", self.config.glslang_validator_path);
let cmd = process::Command::new(&self.config.glslang_validator_path) let cmd = process::Command::new(&self.config.glslang_validator_path)
.args(&["--stdin", "-S", "frag"]) .args(&["--stdin", "-S", "frag"])
.stdin(process::Stdio::piped()) .stdin(process::Stdio::piped())
@ -255,7 +253,7 @@ impl MinecraftShaderLanguageServer {
let output = child.wait_with_output().expect("expected output"); let output = child.wait_with_output().expect("expected output");
let stdout = String::from_utf8(output.stdout).unwrap(); let stdout = String::from_utf8(output.stdout).unwrap();
eprint!("glslangValidator output: {}\n", stdout); eprintln!("glslangValidator output: {}\n", stdout);
let mut diagnostics: Vec<Diagnostic> = vec![]; let mut diagnostics: Vec<Diagnostic> = vec![];
@ -267,7 +265,7 @@ impl MinecraftShaderLanguageServer {
None => return None => return
}; };
eprint!("match {:?}", diagnostic_capture); eprintln!("match {:?}", diagnostic_capture);
let msg = diagnostic_capture.get(4).unwrap().as_str().trim(); let msg = diagnostic_capture.get(4).unwrap().as_str().trim();
@ -397,7 +395,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
} }
fn shutdown(&mut self, _: (), completable: LSCompletable<()>) { fn shutdown(&mut self, _: (), completable: LSCompletable<()>) {
eprint!("shutting down language server..."); eprintln!("shutting down language server...");
completable.complete(Ok(())); completable.complete(Ok(()));
} }
@ -422,13 +420,13 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
.unwrap(); .unwrap();
} }
eprint!("{:?}", params.settings.as_object().unwrap()); eprintln!("{:?}", params.settings.as_object().unwrap());
self.wait.done(); self.wait.done();
} }
fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams) { fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams) {
eprint!("opened doc {}", params.text_document.uri); eprintln!("opened doc {}", params.text_document.uri);
let diagnostics = self.lint(params.text_document.text); let diagnostics = self.lint(params.text_document.text);
self.publish_diagnostic(diagnostics, params.text_document.uri, Some(params.text_document.version)); self.publish_diagnostic(diagnostics, params.text_document.uri, Some(params.text_document.version));
} }
@ -438,7 +436,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
#[allow(unused_variables)] #[allow(unused_variables)]
let text_change = params.content_changes[0].clone(); let text_change = params.content_changes[0].clone();
//eprint!("changed {} changes: {}", text_change., params.text_document.uri); //eprintln!("changed {} changes: {}", text_change., params.text_document.uri);
} }
fn did_close_text_document(&mut self, _: DidCloseTextDocumentParams) {} fn did_close_text_document(&mut self, _: DidCloseTextDocumentParams) {}
@ -485,7 +483,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
.execute(params.command.as_ref(), params.arguments) .execute(params.command.as_ref(), params.arguments)
{ {
Ok(_) => { Ok(_) => {
eprint!("executed {} successfully", params.command); eprintln!("executed {} successfully", params.command);
self.endpoint.send_notification(ShowMessage::METHOD, ShowMessageParams { self.endpoint.send_notification(ShowMessage::METHOD, ShowMessageParams {
typ: MessageType::Info, typ: MessageType::Info,
message: format!("Command {} executed successfully.", params.command), message: format!("Command {} executed successfully.", params.command),
@ -500,7 +498,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
typ: MessageType::Error, typ: MessageType::Error,
message: format!("Failed to execute command '{}'", params.command), message: format!("Failed to execute command '{}'", params.command),
}).expect("failed to send popup/show message notification"); }).expect("failed to send popup/show message notification");
eprint!("failed to execute {}: {}", params.command, err); eprintln!("failed to execute {}: {}", params.command, err);
completable.complete(Err(MethodError::new(32420, err, ()))) completable.complete(Err(MethodError::new(32420, err, ())))
}, },
} }
@ -543,7 +541,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
} }
fn document_link(&mut self, params: DocumentLinkParams, completable: LSCompletable<Vec<DocumentLink>>) { fn document_link(&mut self, params: DocumentLinkParams, completable: LSCompletable<Vec<DocumentLink>>) {
eprint!("document link file: {:?}", params.text_document.uri.to_file_path().unwrap()); eprintln!("document link file: {:?}", params.text_document.uri.to_file_path().unwrap());
// node for current document // node for current document
let curr_doc = params let curr_doc = params
.text_document .text_document
@ -572,7 +570,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
let url = match Url::from_file_path(path) { let url = match Url::from_file_path(path) {
Ok(url) => url, Ok(url) => url,
Err(e) => { Err(e) => {
eprint!("error converting {:?} into url: {:?}", path, e); eprintln!("error converting {:?} into url: {:?}", path, e);
return None; return None;
} }
}; };
@ -589,7 +587,7 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
}) })
}) })
.collect(); .collect();
eprint!("links: {:?}", edges); eprintln!("links: {:?}", edges);
completable.complete(Ok(edges)); completable.complete(Ok(edges));
} }

View file

@ -44,7 +44,7 @@ impl<'a> Invokeable for GraphDotCommand {
let rootpath = params.get(0).unwrap().to_string(); let rootpath = params.get(0).unwrap().to_string();
let rootpath = String::from(rootpath.trim_start_matches('"').trim_end_matches('"')); let rootpath = String::from(rootpath.trim_start_matches('"').trim_end_matches('"'));
let filepath = rootpath + "/graph.dot"; let filepath = rootpath + "/graph.dot";
eprint!("generating dot file at {}", filepath); eprintln!("generating dot file at {}", filepath);
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)

View file

@ -5,7 +5,6 @@
"outDir": "./client/out", "outDir": "./client/out",
"rootDir": "./client/src", "rootDir": "./client/src",
"sourceMap": true, "sourceMap": true,
//"skipLibCheck": true
}, },
"include": [ "include": [
"./client" "./client"

View file

@ -1,44 +0,0 @@
{
"defaultSeverity": "warning",
"extends": ["tslint:recommended"],
"rules": {
"quotemark": [true, "single"],
"comment-format": false,
"semicolon": [true, "never"],
"no-conditional-assignment": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-string-literal": false,
"array-type": false,
"interface-name": false,
"indent": [true, "spaces", 2],
"triple-equals": false,
"arrow-parens": false,
"max-classes-per-file": false,
"no-console": false,
"object-literal-key-quotes": false,
"object-literal-shorthand": {
"severity": "warning"
},
"eofline": false,
"member-ordering": false,
"interface-over-type-literal": false,
"trailing-comma": false,
"no-namespace": false,
"no-var-requires": false,
"max-line-length": {
"severity": "warning",
"options": [170]
},
"radix": false,
"no-empty": false,
"prefer-const": {
"severity": "warning"
},
"curly": [true, "ignore-same-line"],
"whitespace": false,
"no-trailing-whitespace": {
"severity": "warning"
}
}
}