Moved config back to lang server. Temp removed comment checking (it was bad anyways). Only adding in extension if it doesnt already exist. Fixed token replacer

This commit is contained in:
Noah Santschi-Cooney 2018-07-14 19:34:04 +01:00
parent f8edaa549c
commit db321c8566
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
9 changed files with 71 additions and 106 deletions

12
.vscode/tasks.json vendored
View file

@ -46,8 +46,8 @@
"script": "watch:client", "script": "watch:client",
"isBackground": true, "isBackground": true,
"presentation": { "presentation": {
"echo": true, "echo": false,
"reveal": "always", "reveal": "never",
"focus": false, "focus": false,
"panel": "shared" "panel": "shared"
}, },
@ -60,8 +60,8 @@
"script": "watch:server", "script": "watch:server",
"isBackground": true, "isBackground": true,
"presentation": { "presentation": {
"echo": true, "echo": false,
"reveal": "always", "reveal": "never",
"focus": false, "focus": false,
"panel": "shared" "panel": "shared"
}, },
@ -73,8 +73,8 @@
"label": "watch", "label": "watch",
"isBackground": true, "isBackground": true,
"presentation": { "presentation": {
"echo": true, "echo": false,
"reveal": "always", "reveal": "never",
"focus": false, "focus": false,
"panel": "shared" "panel": "shared"
}, },

View file

@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
### Added ### Added
- Deletion of temp files when VSCode closed. - Incomplete completion items
- Support for #include directives
- Basic linting with highlighting. - Basic linting with highlighting.
- Support for .fsh, .vsh, .glsl and .gsh files. - Support for .fsh, .vsh, .glsl and .gsh files.

View file

@ -13,7 +13,7 @@ VSCode-MC-Shader is a [Visual Studio Code](https://code.visualstudio.com/) exten
- Linting (unpolished) - Linting (unpolished)
- Syntax highlighting (by extension dependency) - Syntax highlighting (by extension dependency)
- Support for `#includes` (WIP) - Support for `#includes` directives
- Auto-complete prompts (incomplete) - Auto-complete prompts (incomplete)
## Planned ## Planned

View file

@ -1,39 +0,0 @@
import * as vscode from 'vscode'
import { execSync } from 'child_process'
import * as vscodeLang from 'vscode-languageclient'
export class Config {
public readonly shaderpacksPath: string
public readonly glslangPath: string
constructor(shaderpacksPath: string, glslangPath: string) {
this.shaderpacksPath = shaderpacksPath
this.glslangPath = glslangPath || 'glslangValidator'
}
}
let conf = new Config('', '')
export async function configChangeHandler(langServer: vscodeLang.LanguageClient, event?: vscode.ConfigurationChangeEvent) {
if (event && !event.affectsConfiguration('mcglsl')) return
const temp = vscode.workspace.getConfiguration('mcglsl')
conf = new Config(temp.get('shaderpacksPath'), temp.get('glslangValidatorPath'))
try {
execSync(conf.glslangPath)
langServer.sendNotification(vscodeLang.DidChangeConfigurationNotification.type)
} catch (e) {
if (e.status !== 1) {
const selected = await vscode.window.showErrorMessage(
`[mc-glsl] glslangValidator not found at: '${conf.glslangPath}' or returned non-0 code`,
'Download',
'Cancel'
)
if (selected === 'Download') {
//TODO can i use the python script?
}
}
}
}

View file

@ -1,7 +1,6 @@
import * as vscode from 'vscode' import * as vscode from 'vscode'
import * as vscodeLang from 'vscode-languageclient' import * as vscodeLang from 'vscode-languageclient'
import * as path from 'path' import * as path from 'path'
import { Config, configChangeHandler } from './config'
export function activate(context: vscode.ExtensionContext) { export function activate(context: vscode.ExtensionContext) {
const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js')) const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js'))
@ -20,17 +19,12 @@ export function activate(context: vscode.ExtensionContext) {
const clientOpts: vscodeLang.LanguageClientOptions = { const clientOpts: vscodeLang.LanguageClientOptions = {
documentSelector: [{scheme: 'file', language: 'glsl'}], documentSelector: [{scheme: 'file', language: 'glsl'}],
synchronize: { synchronize: {
//configurationSection: 'mcglsl', configurationSection: 'mcglsl',
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}') fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}')
} }
} }
const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts) const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts)
configChangeHandler(langServer)
vscode.workspace.onDidChangeConfiguration((e) => {
configChangeHandler(langServer, e)
})
context.subscriptions.push(langServer.start()) context.subscriptions.push(langServer.start())
} }

View file

@ -53,7 +53,7 @@
"mcglsl.lintOnType": { "mcglsl.lintOnType": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Whether or not to lint while typing. Can decrease performance." "description": "Whether or not to lint while typing. May decrease performance."
}, },
"mcglsl.shaderpacksPath": { "mcglsl.shaderpacksPath": {
"type": "string", "type": "string",

View file

@ -1,7 +1,7 @@
{ {
"name": "vscode-mc-shader-server", "name": "vscode-mc-shader-server",
"description": "A Visual Studio Code extension for linting/etc Minecraft GLSL Shaders", "description": "A Language Server for linting/etc Minecraft GLSL Shaders",
"version": "0.0.1", "version": "0.8.0",
"author": "Noah Santschi-Cooney (Strum355)", "author": "Noah Santschi-Cooney (Strum355)",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,5 +1,5 @@
import { conf, connection, documents } from './server'
import { TextDocument, Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver' import { TextDocument, Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'
import { conf, connection, documents } from './server'
import { execSync } from 'child_process' import { execSync } from 'child_process'
import * as path from 'path' import * as path from 'path'
import { readFileSync } from 'fs' import { readFileSync } from 'fs'
@ -7,6 +7,7 @@ import { readFileSync } from 'fs'
const reDiag = /^(ERROR|WARNING): ([^?<>:*|"]+?):(\d+): (?:'.*?' : )?(.+)$/ const reDiag = /^(ERROR|WARNING): ([^?<>:*|"]+?):(\d+): (?:'.*?' : )?(.+)$/
const reVersion = /#version [\d]{3}/ const reVersion = /#version [\d]{3}/
const reInclude = /^(?:\s)*?(?:#include) "((?:\/?[^?<>:*|"]+?)+?\.(?:[a-zA-Z]+?))"$/ const reInclude = /^(?:\s)*?(?:#include) "((?:\/?[^?<>:*|"]+?)+?\.(?:[a-zA-Z]+?))"$/
const reIncludeExt = /#extension GL_GOOGLE_include_directive ?: ?require/
const include = '#extension GL_GOOGLE_include_directive : require' const include = '#extension GL_GOOGLE_include_directive : require'
const filters = [ const filters = [
@ -64,20 +65,17 @@ enum Comment {
} }
export function preprocess(lines: string[], docURI: string) { export function preprocess(lines: string[], docURI: string) {
let inComment = false if (lines.find((value: string, i: number, obj: string[]): boolean => reIncludeExt.test(value)) == undefined) {
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
const line = lines[i] const line = lines[i]
//TODO something better than this if (reVersion.test(line)) {
if (line.includes('/*')) inComment = true lines.splice(i + 1, 0, include)
if (line.includes('*/')) inComment = false break
if (line.trim().startsWith('//')) continue }
if (!inComment && reVersion.test(line)) { if (i === lines.length - 1) {
lines.splice(i + 1, 0, include) lines.splice(0, 0, include)
break break
} }
if (i === lines.length - 1) {
lines.splice(0, 0, include)
break
} }
} }
@ -104,6 +102,7 @@ function processIncludes(lines: string[], incStack: string[]) {
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[]) { function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[]) {
const incPath = absPath(inc.parent, inc.match[1]) const incPath = absPath(inc.parent, inc.match[1])
if (!incPath) return false
const dataLines = readFileSync(incPath).toString().split('\n') const dataLines = readFileSync(incPath).toString().split('\n')
incStack.push(incPath) incStack.push(incPath)
@ -121,39 +120,40 @@ export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '')
export function getIncludes(uri: string, lines: string[]) { export function getIncludes(uri: string, lines: string[]) {
const out: IncludeObj[] = [] const out: IncludeObj[] = []
const count = [0] // for each file we need to track the line number const count = [-1] // for each file we need to track the line number
const parStack = [uri] // for each include we need to track its parent const parStack = [uri] // for each include we need to track its parent
let total = 0 // current line number overall let total = -1 // current line number overall
let comment = Comment.No let comment = Comment.No
lines.forEach(line => { lines.forEach(line => {
comment = isInComment(line, comment) comment = isInComment(line, comment)
if (!comment) {
const match = line.match(reInclude)
if (line.startsWith('#line')) {
const inc = line.slice(line.indexOf('"') + 1, line.lastIndexOf('"'))
if (inc === parStack[parStack.length - 2]) {
count.pop()
parStack.pop()
} else {
count.push(0)
parStack.push(inc)
}
} else if (match) {
out.push({
lineNum: count[count.length - 1],
lineNumParent: total,
parent: parStack[parStack.length - 1],
match
})
}
}
count[count.length - 1]++ count[count.length - 1]++
total++ total++
if (comment) return
if (line.startsWith('#line')) {
const inc = line.slice(line.indexOf('"') + 1, line.lastIndexOf('"'))
if (inc === parStack[parStack.length - 2]) {
count.pop()
parStack.pop()
} else {
count.push(-1)
parStack.push(inc)
}
return
}
const match = line.match(reInclude)
if (match) {
out.push({
lineNum: count[count.length - 1],
lineNumParent: total,
parent: parStack[parStack.length - 1],
match
})
}
}) })
return out return out
} }
@ -167,8 +167,8 @@ export function isInComment(line: string, state: Comment): Comment {
} }
export function absPath(currFile: string, includeFile: string): string { export function absPath(currFile: string, includeFile: string): string {
if (!currFile.startsWith(conf.shaderpacksPath)) { if (!currFile.startsWith(conf.shaderpacksPath) || conf.shaderpacksPath === '') {
connection.window.showErrorMessage(`Shaderpacks path may not be correct. Current file is in ${currFile} but the path is set to ${conf.shaderpacksPath}`) connection.window.showErrorMessage(`Shaderpacks path may not be correct. Current file is in '${currFile}' but the path is set to '${conf.shaderpacksPath}'`)
return return
} }
@ -181,7 +181,7 @@ export function absPath(currFile: string, includeFile: string): string {
} }
function lint(uri: string, lines: string[], includes: string[]) { function lint(uri: string, lines: string[], includes: string[]) {
//console.log(lines.join('\n')) console.log(lines.join('\n'))
//return //return
let out: string = '' let out: string = ''
try { try {
@ -211,7 +211,7 @@ function lint(uri: string, lines: string[], includes: string[]) {
}) })
} }
export const replaceWord = (msg: string) => Object.entries(tokens).reduce((acc, [key, value]) => acc.replace(key, value), msg) export const replaceWord = (msg: string) => Array.from(tokens.entries()).reduce((acc, [key, value]) => acc.replace(key, value), msg)
const daigsArray = (diags: Map<string, Diagnostic[]>) => Array.from(diags).map(kv => ({uri: 'file://' + kv[0], diag: kv[1]})) const daigsArray = (diags: Map<string, Diagnostic[]>) => Array.from(diags).map(kv => ({uri: 'file://' + kv[0], diag: kv[1]}))

View file

@ -1,5 +1,5 @@
import * as vsclang from 'vscode-languageserver' import * as vsclang from 'vscode-languageserver'
import { TextDocumentChangeEvent, TextDocument } from 'vscode-languageserver-protocol' import * as vsclangproto from 'vscode-languageserver-protocol'
import { Config } from './config' import { Config } from './config'
import { completions } from './completionProvider' import { completions } from './completionProvider'
import { preprocess, ext, formatURI } from './linter' import { preprocess, ext, formatURI } from './linter'
@ -32,12 +32,16 @@ documents.onDidSave((event) => onEvent(event.document))
//documents.onDidChangeContent(onEvent) //documents.onDidChangeContent(onEvent)
function onEvent(document: TextDocument) { function onEvent(document: vsclangproto.TextDocument) {
if (!ext.has(extname(document.uri))) return if (!ext.has(extname(document.uri))) return
preprocess(document.getText().split('\n'), formatURI(document.uri)) try {
preprocess(document.getText().split('\n'), formatURI(document.uri))
} catch (e) {
connection.window.showErrorMessage(`[mc-glsl] ${e.message}`)
}
} }
connection.onDidChangeConfiguration((change) => { connection.onDidChangeConfiguration(async (change) => {
const temp = change.settings.mcglsl as Config const temp = change.settings.mcglsl as Config
conf = new Config(temp['shaderpacksPath'], temp['glslangValidatorPath']) conf = new Config(temp['shaderpacksPath'], temp['glslangValidatorPath'])
try { try {
@ -45,7 +49,12 @@ connection.onDidChangeConfiguration((change) => {
documents.all().forEach(document => onEvent) documents.all().forEach(document => onEvent)
} catch (e) { } catch (e) {
if (e.status !== 1) { if (e.status !== 1) {
connection.window.showErrorMessage(`[mc-glsl] glslangValidator not found at: '${conf.glslangPath}' or returned non-0 code`) 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)
} }
} }
}) })