Skip to content

Commit c953677

Browse files
committed
Moving from maps of maps to a more sophisticated graph class for includes
1 parent 18c0e2e commit c953677

File tree

3 files changed

+49
-31
lines changed

3 files changed

+49
-31
lines changed

server/src/graph.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ export class Graph {
2323
}
2424
this.nodes.set(parent, par)
2525
}
26+
27+
public get(uri: string): Node {
28+
if (!this.nodes.has(uri)) this.nodes.set(uri, {parents: new Map(), children: new Map()})
29+
return this.nodes.get(uri)
30+
}
2631
}

server/src/linter.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'
22
import { connection, documents } from './server'
33
import { execSync } from 'child_process'
44
import * as path from 'path'
5-
import { readFileSync, existsSync } from 'fs'
5+
import { readFileSync, existsSync, statSync, Stats } from 'fs'
66
import { conf } from './config'
77
import { postError, formatURI, getDocumentContents } from './utils'
88
import { platform } from 'os'
@@ -11,7 +11,7 @@ import { Comment } from './comment'
1111

1212
const reDiag = /^(ERROR|WARNING): ([^?<>*|"]+?):(\d+): (?:'.*?' : )?(.+)\r?/
1313
const reVersion = /#version [\d]{3}/
14-
const reInclude = /^(?:\s)*?(?:#include) "((?:\/?[^?<>:*|"]+?)+?\.(?:[a-zA-Z]+?))"\r?/
14+
const reInclude = /^(?:\s)*?(?:#include) "(.+)"\r?/
1515
const reIncludeExt = /#extension GL_GOOGLE_include_directive ?: ?require/
1616
const include = '#extension GL_GOOGLE_include_directive : require'
1717
const win = platform() === 'win32'
@@ -25,7 +25,6 @@ const filters = [
2525

2626
export const includeGraph = new Graph()
2727

28-
export const includeToParent = new Map<string, Set<string>>()
2928
export const allFiles = new Set<string>()
3029

3130
type IncludeObj = {
@@ -99,17 +98,14 @@ export function preprocess(lines: string[], docURI: string) {
9998
lint(docURI, lines, includeMap, diagnostics)
10099
}
101100

102-
function buildIncludeTree(inc: IncludeObj) {
103-
if (!includeToParent.has(inc.path)) includeToParent.set(inc.path, new Set([inc.parent]))
104-
else includeToParent.get(inc.path).add(inc.parent)
105-
}
101+
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent)
106102

107103
function processIncludes(lines: string[], incStack: string[], allIncludes: IncludeObj[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
108104
const includes = getIncludes(incStack[0], lines)
109105
allIncludes.push(...includes)
110106
if (includes.length > 0) {
111107
includes.reverse().forEach(inc => {
112-
buildIncludeTree(inc)
108+
buildIncludeGraph(inc)
113109
mergeInclude(inc, lines, incStack, diagnostics, hasDirective)
114110
})
115111
// recursively check for more includes to be merged
@@ -162,24 +158,40 @@ export function getIncludes(uri: string, lines: string[]) {
162158
}, [])
163159
}
164160

161+
function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>) {
162+
const range = calcRange(inc.lineNumTopLevel - (win ? 1 : 0), incStack[0])
163+
diagnostics.set(
164+
inc.parent,
165+
[
166+
...(diagnostics.get(inc.parent) || []),
167+
{
168+
severity: DiagnosticSeverity.Error,
169+
range,
170+
message: `${inc.path.replace(conf.shaderpacksPath, '')} is missing or an invalid file.`,
171+
source: 'mc-glsl'
172+
}
173+
]
174+
)
175+
lines[inc.lineNumTopLevel] = ''
176+
}
177+
165178
function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
166-
if (!existsSync(inc.path)) {
167-
const range = calcRange(inc.lineNumTopLevel - (win ? 1 : 0), incStack[0])
168-
diagnostics.set(
169-
inc.parent,
170-
[
171-
...(diagnostics.get(inc.parent) || []),
172-
{
173-
severity: DiagnosticSeverity.Error,
174-
range,
175-
message: `${inc.path.replace(conf.shaderpacksPath, '')} is missing.`,
176-
source: 'mc-glsl'
177-
}
178-
]
179-
)
180-
lines[inc.lineNumTopLevel] = ''
179+
let stats: Stats
180+
try {
181+
stats = statSync(inc.path)
182+
} catch (e) {
183+
if (e.code === 'ENOENT') {
184+
ifInvalidFile(inc, lines, incStack, diagnostics)
185+
return
186+
}
187+
throw e
188+
}
189+
190+
if (!stats.isFile()) {
191+
ifInvalidFile(inc, lines, incStack, diagnostics)
181192
return
182193
}
194+
183195
const dataLines = readFileSync(inc.path).toString().split('\n')
184196

185197
// 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
230242
// TODO what if we dont know the top level parent? Feel like thats a non-issue given that we have uri
231243
diag = {
232244
severity: errorType(type),
233-
// TODO put -1 back when #11 is sorted
234245
range: calcRange(includes.get(nextFile).lineNum, includes.get(nextFile).parent),
235246
message: `Line ${line} ${includes.get(file).path.replace(conf.shaderpacksPath, '')} ${replaceWords(msg)}`,
236247
source: 'mc-glsl'

server/src/server.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as vsclang from 'vscode-languageserver'
22
import * as vsclangproto from 'vscode-languageserver-protocol'
33
import { completions } from './completionProvider'
4-
import { preprocess, ext, includeToParent } from './linter'
4+
import { preprocess, ext, includeToParent, includeGraph } from './linter'
55
import { extname } from 'path'
66

77
const reVersion = /#version [\d]{3}/
@@ -39,7 +39,7 @@ documents.onDidClose((event) => connection.sendDiagnostics({uri: event.document.
3939

4040
export function onEvent(document: vsclangproto.TextDocument) {
4141
const uri = formatURI(document.uri)
42-
if (includeToParent.has(uri)) {
42+
if (includeGraph.get(uri).parents.size > 0) {
4343
lintBubbleDown(uri, document)
4444
return
4545
}
@@ -54,13 +54,15 @@ export function onEvent(document: vsclangproto.TextDocument) {
5454
}
5555

5656
function lintBubbleDown(uri: string, document: vsclangproto.TextDocument) {
57-
includeToParent.get(uri).forEach(parent => {
58-
if (includeToParent.has(parent)) {
59-
lintBubbleDown(parent, document)
57+
includeGraph.get(uri).parents.forEach((parent, parentURI) => {
58+
console.log(parentURI)
59+
console.log(parent.parents)
60+
if (parent.parents.size > 0) {
61+
lintBubbleDown(parentURI, document)
6062
} else {
61-
const lines = getDocumentContents(parent).split('\n')
63+
const lines = getDocumentContents(parentURI).split('\n')
6264
if (lines.filter(l => reVersion.test(l)).length > 0) {
63-
preprocess(lines, parent)
65+
preprocess(lines, parentURI)
6466
}
6567
}
6668
})

0 commit comments

Comments
 (0)