mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-07-19 17:26:13 +00:00
Moving from maps of maps to a more sophisticated graph class for includes
This commit is contained in:
parent
18c0e2ef5c
commit
c95367739f
3 changed files with 49 additions and 31 deletions
|
@ -23,4 +23,9 @@ export class Graph {
|
|||
}
|
||||
this.nodes.set(parent, par)
|
||||
}
|
||||
|
||||
public get(uri: string): Node {
|
||||
if (!this.nodes.has(uri)) this.nodes.set(uri, {parents: new Map(), children: new Map()})
|
||||
return this.nodes.get(uri)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'
|
|||
import { connection, documents } from './server'
|
||||
import { execSync } from 'child_process'
|
||||
import * as path from 'path'
|
||||
import { readFileSync, existsSync } from 'fs'
|
||||
import { readFileSync, existsSync, statSync, Stats } from 'fs'
|
||||
import { conf } from './config'
|
||||
import { postError, formatURI, getDocumentContents } from './utils'
|
||||
import { platform } from 'os'
|
||||
|
@ -11,7 +11,7 @@ import { Comment } from './comment'
|
|||
|
||||
const reDiag = /^(ERROR|WARNING): ([^?<>*|"]+?):(\d+): (?:'.*?' : )?(.+)\r?/
|
||||
const reVersion = /#version [\d]{3}/
|
||||
const reInclude = /^(?:\s)*?(?:#include) "((?:\/?[^?<>:*|"]+?)+?\.(?:[a-zA-Z]+?))"\r?/
|
||||
const reInclude = /^(?:\s)*?(?:#include) "(.+)"\r?/
|
||||
const reIncludeExt = /#extension GL_GOOGLE_include_directive ?: ?require/
|
||||
const include = '#extension GL_GOOGLE_include_directive : require'
|
||||
const win = platform() === 'win32'
|
||||
|
@ -25,7 +25,6 @@ const filters = [
|
|||
|
||||
export const includeGraph = new Graph()
|
||||
|
||||
export const includeToParent = new Map<string, Set<string>>()
|
||||
export const allFiles = new Set<string>()
|
||||
|
||||
type IncludeObj = {
|
||||
|
@ -99,17 +98,14 @@ export function preprocess(lines: string[], docURI: string) {
|
|||
lint(docURI, lines, includeMap, diagnostics)
|
||||
}
|
||||
|
||||
function buildIncludeTree(inc: IncludeObj) {
|
||||
if (!includeToParent.has(inc.path)) includeToParent.set(inc.path, new Set([inc.parent]))
|
||||
else includeToParent.get(inc.path).add(inc.parent)
|
||||
}
|
||||
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent)
|
||||
|
||||
function processIncludes(lines: string[], incStack: string[], allIncludes: IncludeObj[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||
const includes = getIncludes(incStack[0], lines)
|
||||
allIncludes.push(...includes)
|
||||
if (includes.length > 0) {
|
||||
includes.reverse().forEach(inc => {
|
||||
buildIncludeTree(inc)
|
||||
buildIncludeGraph(inc)
|
||||
mergeInclude(inc, lines, incStack, diagnostics, hasDirective)
|
||||
})
|
||||
// recursively check for more includes to be merged
|
||||
|
@ -162,8 +158,7 @@ export function getIncludes(uri: string, lines: string[]) {
|
|||
}, [])
|
||||
}
|
||||
|
||||
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||
if (!existsSync(inc.path)) {
|
||||
function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>) {
|
||||
const range = calcRange(inc.lineNumTopLevel - (win ? 1 : 0), incStack[0])
|
||||
diagnostics.set(
|
||||
inc.parent,
|
||||
|
@ -172,14 +167,31 @@ function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diag
|
|||
{
|
||||
severity: DiagnosticSeverity.Error,
|
||||
range,
|
||||
message: `${inc.path.replace(conf.shaderpacksPath, '')} is missing.`,
|
||||
message: `${inc.path.replace(conf.shaderpacksPath, '')} is missing or an invalid file.`,
|
||||
source: 'mc-glsl'
|
||||
}
|
||||
]
|
||||
)
|
||||
lines[inc.lineNumTopLevel] = ''
|
||||
}
|
||||
|
||||
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
|
||||
let stats: Stats
|
||||
try {
|
||||
stats = statSync(inc.path)
|
||||
} catch (e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
ifInvalidFile(inc, lines, incStack, diagnostics)
|
||||
return
|
||||
}
|
||||
throw e
|
||||
}
|
||||
|
||||
if (!stats.isFile()) {
|
||||
ifInvalidFile(inc, lines, incStack, diagnostics)
|
||||
return
|
||||
}
|
||||
|
||||
const dataLines = readFileSync(inc.path).toString().split('\n')
|
||||
|
||||
// if the includes parent is the top level (aka where the include directive is placed)
|
||||
|
@ -230,7 +242,6 @@ function lint(uri: string, lines: string[], includes: Map<string, IncludeObj>, d
|
|||
// TODO what if we dont know the top level parent? Feel like thats a non-issue given that we have uri
|
||||
diag = {
|
||||
severity: errorType(type),
|
||||
// TODO put -1 back when #11 is sorted
|
||||
range: calcRange(includes.get(nextFile).lineNum, includes.get(nextFile).parent),
|
||||
message: `Line ${line} ${includes.get(file).path.replace(conf.shaderpacksPath, '')} ${replaceWords(msg)}`,
|
||||
source: 'mc-glsl'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as vsclang from 'vscode-languageserver'
|
||||
import * as vsclangproto from 'vscode-languageserver-protocol'
|
||||
import { completions } from './completionProvider'
|
||||
import { preprocess, ext, includeToParent } from './linter'
|
||||
import { preprocess, ext, includeToParent, includeGraph } from './linter'
|
||||
import { extname } from 'path'
|
||||
|
||||
const reVersion = /#version [\d]{3}/
|
||||
|
@ -39,7 +39,7 @@ documents.onDidClose((event) => connection.sendDiagnostics({uri: event.document.
|
|||
|
||||
export function onEvent(document: vsclangproto.TextDocument) {
|
||||
const uri = formatURI(document.uri)
|
||||
if (includeToParent.has(uri)) {
|
||||
if (includeGraph.get(uri).parents.size > 0) {
|
||||
lintBubbleDown(uri, document)
|
||||
return
|
||||
}
|
||||
|
@ -54,13 +54,15 @@ export function onEvent(document: vsclangproto.TextDocument) {
|
|||
}
|
||||
|
||||
function lintBubbleDown(uri: string, document: vsclangproto.TextDocument) {
|
||||
includeToParent.get(uri).forEach(parent => {
|
||||
if (includeToParent.has(parent)) {
|
||||
lintBubbleDown(parent, document)
|
||||
includeGraph.get(uri).parents.forEach((parent, parentURI) => {
|
||||
console.log(parentURI)
|
||||
console.log(parent.parents)
|
||||
if (parent.parents.size > 0) {
|
||||
lintBubbleDown(parentURI, document)
|
||||
} else {
|
||||
const lines = getDocumentContents(parent).split('\n')
|
||||
const lines = getDocumentContents(parentURI).split('\n')
|
||||
if (lines.filter(l => reVersion.test(l)).length > 0) {
|
||||
preprocess(lines, parent)
|
||||
preprocess(lines, parentURI)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue