mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-07-19 17:26:13 +00:00
Fixed errors still propogating of the include was removed from the parent. Also supressing 'shaderpacks' path not found
This commit is contained in:
parent
036b6809dc
commit
6fd02abd9d
6 changed files with 52 additions and 26 deletions
|
@ -20,6 +20,7 @@ VSCode-MC-Shader is a [Visual Studio Code](https://code.visualstudio.com/) exten
|
||||||
|
|
||||||
## Planned
|
## Planned
|
||||||
|
|
||||||
|
- Multi-workspaces (currently only one is supported and using multiple is very undefined behaviour)
|
||||||
- Warnings for unused uniforms/varyings
|
- Warnings for unused uniforms/varyings
|
||||||
- Some cool `DRAWBUFFERS` stuff
|
- Some cool `DRAWBUFFERS` stuff
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { postError } from './utils'
|
||||||
import { execSync } from 'child_process'
|
import { execSync } from 'child_process'
|
||||||
import { serverLog } from './logging'
|
import { serverLog } from './logging'
|
||||||
import { dirname } from 'path'
|
import { dirname } from 'path'
|
||||||
|
import { DidChangeConfigurationParams } from 'vscode-languageserver/lib/main'
|
||||||
|
|
||||||
const url = {
|
const url = {
|
||||||
'win32': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-windows-x64-Release.zip',
|
'win32': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-windows-x64-Release.zip',
|
||||||
|
@ -23,7 +24,9 @@ export interface Config {
|
||||||
|
|
||||||
export let conf: Config = {shaderpacksPath: '', glslangPath: ''}
|
export let conf: Config = {shaderpacksPath: '', glslangPath: ''}
|
||||||
|
|
||||||
export const onConfigChange = async (change) => {
|
let supress = false
|
||||||
|
|
||||||
|
export async function onConfigChange(change: DidChangeConfigurationParams) {
|
||||||
const temp = change.settings.mcglsl as Config
|
const temp = change.settings.mcglsl as Config
|
||||||
if (temp.shaderpacksPath === conf.shaderpacksPath && temp.glslangPath === conf.glslangPath) return
|
if (temp.shaderpacksPath === conf.shaderpacksPath && temp.glslangPath === conf.glslangPath) return
|
||||||
conf = {shaderpacksPath: temp['shaderpacksPath'].replace(/\\/g, '/'), glslangPath: temp['glslangValidatorPath'].replace(/\\/g, '/')}
|
conf = {shaderpacksPath: temp['shaderpacksPath'].replace(/\\/g, '/'), glslangPath: temp['glslangValidatorPath'].replace(/\\/g, '/')}
|
||||||
|
@ -31,8 +34,14 @@ export const onConfigChange = async (change) => {
|
||||||
serverLog.debug(() => 'old config: ' + JSON.stringify(conf))
|
serverLog.debug(() => 'old config: ' + JSON.stringify(conf))
|
||||||
|
|
||||||
if (conf.shaderpacksPath === '' || conf.shaderpacksPath.replace(dirname(conf.shaderpacksPath), '') !== '/shaderpacks') {
|
if (conf.shaderpacksPath === '' || conf.shaderpacksPath.replace(dirname(conf.shaderpacksPath), '') !== '/shaderpacks') {
|
||||||
|
if (supress) return
|
||||||
serverLog.error(() => 'shaderpack path not set or doesn\'t end in \'shaderpacks\'', null)
|
serverLog.error(() => 'shaderpack path not set or doesn\'t end in \'shaderpacks\'', null)
|
||||||
connection.window.showErrorMessage('mcglsl.shaderpacksPath is not set or doesn\'t end in \'shaderpacks\'. Please set it in your settings.')
|
supress = true
|
||||||
|
const clicked = await connection.window.showErrorMessage(
|
||||||
|
'mcglsl.shaderpacksPath is not set or doesn\'t end in \'shaderpacks\'. Please set it in your settings.',
|
||||||
|
{title: 'Supress'}
|
||||||
|
)
|
||||||
|
supress = (clicked && clicked.title === 'Supress') ? true : false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ export type Pair<T, S> = {
|
||||||
second: S
|
second: S
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node = {
|
export type Node = {
|
||||||
parents: Map<string, Pair<number, Node>>
|
parents: Map<string, Pair<number, Node>>
|
||||||
children: Map<string, Node>
|
children: Map<string, Node>
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { readFileSync, existsSync, statSync, Stats } from 'fs'
|
||||||
import { conf } from './config'
|
import { conf } from './config'
|
||||||
import { postError, formatURI, getDocumentContents, trimPath } from './utils'
|
import { postError, formatURI, getDocumentContents, trimPath } from './utils'
|
||||||
import { platform } from 'os'
|
import { platform } from 'os'
|
||||||
import { Graph } from './graph'
|
import { Graph, Node } from './graph'
|
||||||
import { Comment } from './comment'
|
import { Comment } from './comment'
|
||||||
import { linterLog } from './logging'
|
import { linterLog } from './logging'
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ export function preprocess(lines: string[], docURI: string) {
|
||||||
|
|
||||||
const includeMap = new Map<string, IncludeObj>(Array.from(allIncludes).map(obj => [obj.path, obj]) as [string, IncludeObj][])
|
const includeMap = new Map<string, IncludeObj>(Array.from(allIncludes).map(obj => [obj.path, obj]) as [string, IncludeObj][])
|
||||||
|
|
||||||
lint(docURI, lines, includeMap, diagnostics)
|
lint(docURI, lines, includeMap, diagnostics, hasDirective)
|
||||||
}
|
}
|
||||||
|
|
||||||
function includeDirective(lines: string[], docURI: string): boolean {
|
function includeDirective(lines: string[], docURI: string): boolean {
|
||||||
|
@ -123,11 +123,24 @@ function includeDirective(lines: string[], docURI: string): boolean {
|
||||||
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent, inc.lineNum)
|
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent, inc.lineNum)
|
||||||
|
|
||||||
function processIncludes(lines: string[], incStack: string[], allIncludes: Set<IncludeObj>, diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
function processIncludes(lines: string[], incStack: string[], allIncludes: Set<IncludeObj>, diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||||
|
// todo figure out why incStack[0] here
|
||||||
const includes = getIncludes(incStack[0], lines)
|
const includes = getIncludes(incStack[0], lines)
|
||||||
includes.forEach(i => allIncludes.add(i))
|
includes.forEach(i => allIncludes.add(i))
|
||||||
if (includes.length > 0) {
|
|
||||||
linterLog.info(() => `${trimPath(incStack[0])} has ${includes.length} include(s). [${includes.map(i => '\n\t\t' + trimPath(i.path))}\n\t]`)
|
const parent = incStack[incStack.length - 1]
|
||||||
includes.reverse().forEach(inc => {
|
includeGraph.nodes.get(parent).children.forEach((node, uri) => {
|
||||||
|
if (!includes.has(uri)) {
|
||||||
|
includeGraph.nodes.get(parent).children.delete(uri)
|
||||||
|
node.parents.delete(parent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const includeList = Array.from(includes.values())
|
||||||
|
|
||||||
|
if (includeList.length > 0) {
|
||||||
|
linterLog.info(() => `${trimPath(parent)} has ${includeList.length} include(s). [${includeList.map(i => '\n\t\t' + trimPath(i.path))}\n\t]`)
|
||||||
|
|
||||||
|
includeList.reverse().forEach(inc => {
|
||||||
buildIncludeGraph(inc)
|
buildIncludeGraph(inc)
|
||||||
mergeInclude(inc, lines, incStack, diagnostics, hasDirective)
|
mergeInclude(inc, lines, incStack, diagnostics, hasDirective)
|
||||||
})
|
})
|
||||||
|
@ -137,16 +150,14 @@ function processIncludes(lines: string[], incStack: string[], allIncludes: Set<I
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIncludes(uri: string, lines: string[]) {
|
function getIncludes(uri: string, lines: string[]) {
|
||||||
// the numbers start at -1 because we increment them as soon as we enter the loop so that we
|
|
||||||
// dont have to put an incrememnt at each return
|
|
||||||
const lineInfo: LinesProcessingInfo = {
|
const lineInfo: LinesProcessingInfo = {
|
||||||
total: -1,
|
total: -1,
|
||||||
comment: Comment.State.No,
|
comment: Comment.State.No,
|
||||||
parStack: [uri],
|
parStack: [uri],
|
||||||
count: [-1],
|
count: [0],
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines.reduce<IncludeObj[]>((out, line, i): IncludeObj[] => processLine(out, line, lines, i, lineInfo), [])
|
return new Map(lines.reduce<IncludeObj[]>((out, line, i) => processLine(out, line, lines, i, lineInfo), []).map(inc => [inc.path, inc] as [string, IncludeObj]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO can surely be reworked
|
// TODO can surely be reworked
|
||||||
|
@ -191,7 +202,7 @@ function processLine(includes: IncludeObj[], line: string, lines: string[], i: n
|
||||||
return includes
|
return includes
|
||||||
}
|
}
|
||||||
|
|
||||||
function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>) {
|
function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||||
const msg = `${trimPath(inc.path)} is missing or an invalid file.`
|
const msg = `${trimPath(inc.path)} is missing or an invalid file.`
|
||||||
|
|
||||||
linterLog.error(msg, null)
|
linterLog.error(msg, null)
|
||||||
|
@ -212,7 +223,7 @@ function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], dia
|
||||||
line: inc.lineNum,
|
line: inc.lineNum,
|
||||||
msg, file,
|
msg, file,
|
||||||
}
|
}
|
||||||
propogateDiagnostic(error, diagnostics)
|
propogateDiagnostic(error, diagnostics, hasDirective)
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||||
|
@ -221,14 +232,14 @@ function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diag
|
||||||
stats = statSync(inc.path)
|
stats = statSync(inc.path)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'ENOENT') {
|
if (e.code === 'ENOENT') {
|
||||||
ifInvalidFile(inc, lines, incStack, diagnostics)
|
ifInvalidFile(inc, lines, incStack, diagnostics, hasDirective)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stats.isFile()) {
|
if (!stats.isFile()) {
|
||||||
ifInvalidFile(inc, lines, incStack, diagnostics)
|
ifInvalidFile(inc, lines, incStack, diagnostics, hasDirective)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +259,7 @@ function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diag
|
||||||
lines.splice(inc.lineNumTopLevel + 1 + dataLines.length, 0, `#line ${inc.lineNum + 1} "${inc.parent}"`)
|
lines.splice(inc.lineNumTopLevel + 1 + dataLines.length, 0, `#line ${inc.lineNum + 1} "${inc.parent}"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function lint(docURI: string, lines: string[], includes: Map<string, IncludeObj>, diagnostics: Map<string, Diagnostic[]>) {
|
function lint(docURI: string, lines: string[], includes: Map<string, IncludeObj>, diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||||
let out: string = ''
|
let out: string = ''
|
||||||
try {
|
try {
|
||||||
execSync(`${conf.glslangPath} --stdin -S ${ext.get(path.extname(docURI))}`, {input: lines.join('\n')})
|
execSync(`${conf.glslangPath} --stdin -S ${ext.get(path.extname(docURI))}`, {input: lines.join('\n')})
|
||||||
|
@ -261,7 +272,7 @@ function lint(docURI: string, lines: string[], includes: Map<string, IncludeObj>
|
||||||
if (!diagnostics.has(key)) diagnostics.set(key, [])
|
if (!diagnostics.has(key)) diagnostics.set(key, [])
|
||||||
})
|
})
|
||||||
|
|
||||||
processErrors(out, docURI, diagnostics)
|
processErrors(out, docURI, diagnostics, hasDirective)
|
||||||
|
|
||||||
daigsArray(diagnostics).forEach(d => {
|
daigsArray(diagnostics).forEach(d => {
|
||||||
if (win) d.uri = d.uri.replace('file://C:', 'file:///c%3A')
|
if (win) d.uri = d.uri.replace('file://C:', 'file:///c%3A')
|
||||||
|
@ -269,7 +280,7 @@ function lint(docURI: string, lines: string[], includes: Map<string, IncludeObj>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function processErrors(out: string, docURI: string, diagnostics: Map<string, Diagnostic[]>) {
|
function processErrors(out: string, docURI: string, diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||||
filterMatches(out).forEach(match => {
|
filterMatches(out).forEach(match => {
|
||||||
const error: ErrorMatch = {
|
const error: ErrorMatch = {
|
||||||
type: errorType(match[1]),
|
type: errorType(match[1]),
|
||||||
|
@ -289,16 +300,16 @@ function processErrors(out: string, docURI: string, diagnostics: Map<string, Dia
|
||||||
diagnostics.get(error.file.length - 1 ? error.file : docURI).push(diag)
|
diagnostics.get(error.file.length - 1 ? error.file : docURI).push(diag)
|
||||||
|
|
||||||
// if is an include, highlight an error in the parents line of inclusion
|
// if is an include, highlight an error in the parents line of inclusion
|
||||||
propogateDiagnostic(error, diagnostics)
|
propogateDiagnostic(error, diagnostics, hasDirective)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//errorFile: string, type: DiagnosticSeverity, line: number, msg: string
|
//errorFile: string, type: DiagnosticSeverity, line: number, msg: string
|
||||||
function propogateDiagnostic(error: ErrorMatch, diagnostics: Map<string, Diagnostic[]>, parentURI?: string) {
|
function propogateDiagnostic(error: ErrorMatch, diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean, parentURI?: string) {
|
||||||
includeGraph.get(parentURI || error.file).parents.forEach((pair, parURI) => {
|
includeGraph.get(parentURI || error.file).parents.forEach((pair, parURI) => {
|
||||||
const diag: Diagnostic = {
|
const diag: Diagnostic = {
|
||||||
severity: error.type,
|
severity: error.type,
|
||||||
range: calcRange(pair.first - 1, parURI),
|
range: calcRange(pair.first - (pair.second.parents.size > 0 ? 0 : (2 - (hasDirective ? 1 : 0))), parURI),
|
||||||
message: `Line ${error.line} ${trimPath(error.file)} ${replaceWords(error.msg)}`,
|
message: `Line ${error.line} ${trimPath(error.file)} ${replaceWords(error.msg)}`,
|
||||||
source: 'mc-glsl'
|
source: 'mc-glsl'
|
||||||
}
|
}
|
||||||
|
@ -307,7 +318,7 @@ function propogateDiagnostic(error: ErrorMatch, diagnostics: Map<string, Diagnos
|
||||||
diagnostics.get(parURI).push(diag)
|
diagnostics.get(parURI).push(diag)
|
||||||
|
|
||||||
if (pair.second.parents.size > 0) {
|
if (pair.second.parents.size > 0) {
|
||||||
propogateDiagnostic(error, diagnostics, parURI)
|
propogateDiagnostic(error, diagnostics, hasDirective, parURI)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,9 @@ documents.onDidSave((event) => onEvent(event.document))
|
||||||
|
|
||||||
// what am i saying here
|
// what am i saying here
|
||||||
// dont do this for include files, for non-include files, clear diags for all its includes. Cache this maybe
|
// dont do this for include files, for non-include files, clear diags for all its includes. Cache this maybe
|
||||||
documents.onDidClose((event) => connection.sendDiagnostics({uri: event.document.uri, diagnostics: []}))
|
documents.onDidClose((event) => {
|
||||||
|
connection.sendDiagnostics({uri: event.document.uri, diagnostics: []})
|
||||||
|
})
|
||||||
|
|
||||||
//documents.onDidChangeContent(onEvent)
|
//documents.onDidChangeContent(onEvent)
|
||||||
|
|
||||||
|
@ -48,7 +50,9 @@ export function onEvent(document: vsclangproto.TextDocument) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// i think we still need to keep this in case we havent found the root of this files include tree
|
// i think we still need to keep this in case we havent found the root of this files include tree
|
||||||
if (!ext.has(extname(document.uri))) return
|
const lines = document.getText().split('\n')
|
||||||
|
const hasVersion = lines.filter(l => reVersion.test(l)).length > 0
|
||||||
|
if (!ext.has(extname(document.uri)) || !hasVersion) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
preprocess(document.getText().split('\n'), uri)
|
preprocess(document.getText().split('\n'), uri)
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { serverLog } from './logging'
|
||||||
|
|
||||||
export function postError(e: Error) {
|
export function postError(e: Error) {
|
||||||
connection.window.showErrorMessage(e.message)
|
connection.window.showErrorMessage(e.message)
|
||||||
serverLog.error(e.message, new Error())
|
serverLog.error(e.message, null)
|
||||||
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '').replace(/^(?:\/)c%3A/, 'C:').replace(/\\/g, '/')
|
export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '').replace(/^(?:\/)c%3A/, 'C:').replace(/\\/g, '/')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue