mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-08-02 16:13:27 +00:00
Doing more on the extension side and splitting up the lang server linting more
This commit is contained in:
parent
d7d41985ef
commit
cacfbe7a4e
6 changed files with 120 additions and 40 deletions
17
.vscode/tasks.json
vendored
17
.vscode/tasks.json
vendored
|
@ -3,6 +3,23 @@
|
|||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "fix",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "silent",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tslint5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "compile",
|
||||
|
|
39
client/src/config.ts
Normal file
39
client/src/config.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
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?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import * as vscode from 'vscode'
|
||||
import * as vscodeLang from 'vscode-languageclient'
|
||||
import * as path from 'path'
|
||||
import { Config, configChangeHandler } from './config'
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js'))
|
||||
|
@ -19,12 +20,17 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
const clientOpts: vscodeLang.LanguageClientOptions = {
|
||||
documentSelector: [{scheme: 'file', language: 'glsl'}],
|
||||
synchronize: {
|
||||
configurationSection: 'mcglsl',
|
||||
//configurationSection: 'mcglsl',
|
||||
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}')
|
||||
}
|
||||
}
|
||||
|
||||
const disposable = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts)
|
||||
const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts)
|
||||
|
||||
context.subscriptions.push(disposable.start())
|
||||
configChangeHandler(langServer)
|
||||
vscode.workspace.onDidChangeConfiguration((e) => {
|
||||
configChangeHandler(langServer, e)
|
||||
})
|
||||
|
||||
context.subscriptions.push(langServer.start())
|
||||
}
|
|
@ -56,9 +56,7 @@ enum Comment {
|
|||
Multi
|
||||
}
|
||||
|
||||
// TODO exclude exts not in ext
|
||||
export function preprocess(lines: string[], docURI: string, topLevel: boolean, incStack: string[], num: number) {
|
||||
if (topLevel) {
|
||||
export function preprocess(lines: string[], docURI: string) {
|
||||
let inComment = false
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i]
|
||||
|
@ -75,23 +73,9 @@ export function preprocess(lines: string[], docURI: string, topLevel: boolean, i
|
|||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const includes = getIncludes(incStack[0], lines)
|
||||
if (includes.length > 0) {
|
||||
includes.reverse().forEach(inc => {
|
||||
const incPath = absPath(inc.parent, inc.match[1])
|
||||
incStack.push(incPath)
|
||||
const dataLines = readFileSync(incPath).toString().split('\n')
|
||||
lines[inc.lineNumParent] = `#line 0 "${incPath}"`
|
||||
lines.splice(inc.lineNumParent + 1, 0, ...dataLines)
|
||||
lines.splice(inc.lineNumParent + 1 + dataLines.length, 0, `#line ${inc.lineNum} "${inc.parent}"`)
|
||||
|
||||
})
|
||||
preprocess(lines, docURI, false, incStack, num)
|
||||
}
|
||||
|
||||
if (!topLevel) return
|
||||
const incStack = [docURI]
|
||||
processIncludes(lines, incStack)
|
||||
|
||||
try {
|
||||
lint(docURI, lines, incStack)
|
||||
|
@ -100,21 +84,50 @@ export function preprocess(lines: string[], docURI: string, topLevel: boolean, i
|
|||
}
|
||||
}
|
||||
|
||||
function processIncludes(lines: string[], incStack: string[]) {
|
||||
const includes = getIncludes(incStack[0], lines)
|
||||
if (includes.length > 0) {
|
||||
includes.reverse().forEach(inc => {
|
||||
mergeInclude(inc, lines, incStack)
|
||||
})
|
||||
// recursively check for more includes to be merged
|
||||
processIncludes(lines, incStack)
|
||||
}
|
||||
}
|
||||
|
||||
function mergeInclude(inc: {lineNum: number, lineNumParent: number, parent: string, match: RegExpMatchArray}, lines: string[], incStack: string[]) {
|
||||
const incPath = absPath(inc.parent, inc.match[1])
|
||||
const dataLines = readFileSync(incPath).toString().split('\n')
|
||||
incStack.push(incPath)
|
||||
|
||||
// add #line indicating we are entering a new include block
|
||||
lines[inc.lineNumParent] = `#line 0 "${incPath}"`
|
||||
// merge the lines of the file into the current document
|
||||
lines.splice(inc.lineNumParent + 1, 0, ...dataLines)
|
||||
// add the closing #line indicating we're re-entering a block a level up
|
||||
lines.splice(inc.lineNumParent + 1 + dataLines.length, 0, `#line ${inc.lineNum} "${inc.parent}"`)
|
||||
}
|
||||
|
||||
export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '')
|
||||
|
||||
// TODO no
|
||||
export function getIncludes(uri: string, lines: string[]) {
|
||||
const out: {lineNum: number, lineNumParent: number, parent: string, match: RegExpMatchArray}[] = []
|
||||
|
||||
const count = [0] // for each file we need to track the line number
|
||||
let total = 0
|
||||
const parStack = [uri] // for each include we need to track its parent
|
||||
|
||||
let total = 0 // current line number overall
|
||||
let comment = Comment.No
|
||||
|
||||
lines.forEach(line => {
|
||||
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()
|
||||
|
@ -131,6 +144,7 @@ export function getIncludes(uri: string, lines: string[]) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
count[count.length - 1]++
|
||||
total++
|
||||
})
|
||||
|
@ -175,12 +189,14 @@ function lint(uri: string, lines: string[], includes: string[]) {
|
|||
const matches = filterMatches(out)
|
||||
matches.forEach((match) => {
|
||||
const [whole, type, file, line, msg] = match
|
||||
|
||||
const diag: Diagnostic = {
|
||||
severity: type === 'ERROR' ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning,
|
||||
range: calcRange(parseInt(line) - 1, file.length - 1 ? file : uri),
|
||||
message: replaceWord(msg),
|
||||
source: 'mc-glsl'
|
||||
}
|
||||
|
||||
diagnostics.get(file.length - 1 ? file : uri).push(diag)
|
||||
})
|
||||
|
||||
|
@ -201,12 +217,14 @@ const filterMatches = (output: string) => output
|
|||
|
||||
function calcRange(lineNum: number, uri: string): Range {
|
||||
let lines = []
|
||||
|
||||
// TODO better error handling maybe?
|
||||
if (documents.keys().includes('file://' + uri)) {
|
||||
lines = documents.get('file://' + uri).getText().split('\n')
|
||||
} else {
|
||||
lines = readFileSync(uri).toString().split('\n')
|
||||
}
|
||||
|
||||
const line = lines[lineNum]
|
||||
const startOfLine = line.length - line.trimLeft().length
|
||||
const endOfLine = line.slice(0, line.indexOf('//')).trimRight().length + 1
|
||||
|
|
|
@ -34,7 +34,7 @@ documents.onDidSave((event) => onEvent(event.document))
|
|||
|
||||
function onEvent(document: TextDocument) {
|
||||
if (!ext.has(extname(document.uri))) return
|
||||
preprocess(document.getText().split('\n'), formatURI(document.uri), true, [document.uri.replace(/^file:\/\//, '')], 0)
|
||||
preprocess(document.getText().split('\n'), formatURI(document.uri))
|
||||
}
|
||||
|
||||
connection.onDidChangeConfiguration((change) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue