Skip to content

Commit f5af65a

Browse files
committed
Up-propogation of errors works. Now need to handle the case of changing includes
1 parent 24c5b5b commit f5af65a

File tree

4 files changed

+79
-60
lines changed

4 files changed

+79
-60
lines changed

server/src/graph.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
type Node = {
2-
parents: Map<string, Node>
2+
parents: Map<string, Pair<number, Node>>
33
children: Map<string, Node>
44
}
55

@@ -10,14 +10,14 @@ export class Graph {
1010
return this.nodes.has(uri) ? this.nodes.get(uri).parents.size > 0 : false
1111
}
1212

13-
public setParent(uri: string, parent: string) {
13+
public setParent(uri: string, parent: string, lineNum: number) {
1414
const par: Node = this.nodes.has(parent) ? this.nodes.get(parent) : {parents: new Map(), children: new Map()}
1515
if (this.nodes.has(uri)) {
1616
const node = this.nodes.get(uri)
17-
node.parents.set(parent, par)
17+
node.parents.set(parent, {first: lineNum, second: par})
1818
par.children.set(uri, node)
1919
} else {
20-
const node: Node = {parents: new Map([par].map(p => [parent, p]) as [string, Node][]), children: new Map()}
20+
const node: Node = {parents: new Map([par].map(p => [parent, {first: lineNum, second: p}]) as [string, Pair<number, Node>][]), children: new Map()}
2121
par.children.set(uri, node)
2222
this.nodes.set(uri, node)
2323
}
@@ -28,4 +28,10 @@ export class Graph {
2828
if (!this.nodes.has(uri)) this.nodes.set(uri, {parents: new Map(), children: new Map()})
2929
return this.nodes.get(uri)
3030
}
31+
}
32+
33+
// can you imagine that some people out there would import a whole library just for this?
34+
export type Pair<T, S> = {
35+
first: T,
36+
second: S
3137
}

server/src/linter.ts

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export function preprocess(lines: string[], docURI: string) {
9898
lint(docURI, lines, includeMap, diagnostics)
9999
}
100100

101-
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent)
101+
const buildIncludeGraph = (inc: IncludeObj) => includeGraph.setParent(inc.path, inc.parent, inc.lineNum)
102102

103103
function processIncludes(lines: string[], incStack: string[], allIncludes: IncludeObj[], diagnostics: Map<string, Diagnostic[]>, hasDirective: boolean) {
104104
const includes = getIncludes(incStack[0], lines)
@@ -113,49 +113,61 @@ function processIncludes(lines: string[], incStack: string[], allIncludes: Inclu
113113
}
114114
}
115115

116-
// TODO no
116+
type LinesProcessingInfo = {
117+
total: number,
118+
comment: Comment.State,
119+
parStack: string[],
120+
count: number[],
121+
}
122+
123+
// TODO can surely be reworked
117124
export function getIncludes(uri: string, lines: string[]) {
118-
const count = [-1] // for each file we need to track the line number
119-
const parStack = [uri] // for each include we need to track its parent
120-
121-
let total = -1 // current line number overall
122-
let comment = Comment.State.No
123-
124-
return lines.reduce<IncludeObj[]>((out, line, i, l): IncludeObj[] => {
125-
const updated = Comment.update(line, comment)
126-
comment = updated[0]
127-
line = updated[1]
128-
lines[i] = line
129-
130-
count[count.length - 1]++
131-
total++
132-
if (comment) return out
133-
if (line.startsWith('#line')) {
134-
const inc = line.slice(line.indexOf('"') + 1, line.lastIndexOf('"'))
135-
136-
if (inc === parStack[parStack.length - 2]) {
137-
count.pop()
138-
parStack.pop()
139-
} else {
140-
count.push(-1)
141-
parStack.push(inc)
142-
}
143-
return out
144-
}
125+
// the numbers start at -1 because we increment them as soon as we enter the loop so that we
126+
// dont have to put an incrememnt at each return
127+
const lineInfo: LinesProcessingInfo = {
128+
total: -1,
129+
comment: Comment.State.No,
130+
parStack: [uri],
131+
count: [-1],
132+
}
145133

146-
const match = line.match(reInclude)
134+
return lines.reduce<IncludeObj[]>((out, line, i, l): IncludeObj[] => processLine(out, line, lines, i, lineInfo), [])
135+
}
147136

148-
if (match) {
149-
out.push({
150-
path: formatURI(absPath(parStack[parStack.length - 1], match[1])),
151-
lineNum: count[count.length - 1],
152-
lineNumTopLevel: total,
153-
parent: formatURI(parStack[parStack.length - 1]),
154-
match
155-
})
137+
function processLine(includes: IncludeObj[], line: string, lines: string[], i: number, linesInfo: LinesProcessingInfo): IncludeObj[] {
138+
const updated = Comment.update(line, linesInfo.comment)
139+
linesInfo.comment = updated[0]
140+
line = updated[1]
141+
lines[i] = line
142+
143+
linesInfo.count[linesInfo.count.length - 1]++
144+
linesInfo.total++
145+
if (linesInfo.comment) return includes
146+
if (line.startsWith('#line')) {
147+
const inc = line.slice(line.indexOf('"') + 1, line.lastIndexOf('"'))
148+
149+
if (inc === linesInfo.parStack[linesInfo.parStack.length - 2]) {
150+
linesInfo.count.pop()
151+
linesInfo.parStack.pop()
152+
} else {
153+
linesInfo.count.push(-1)
154+
linesInfo.parStack.push(inc)
156155
}
157-
return out
158-
}, [])
156+
return includes
157+
}
158+
159+
const match = line.match(reInclude)
160+
161+
if (match) {
162+
includes.push({
163+
path: formatURI(absPath(linesInfo.parStack[linesInfo.parStack.length - 1], match[1])),
164+
lineNum: linesInfo.count[linesInfo.count.length - 1],
165+
lineNumTopLevel: linesInfo.total,
166+
parent: formatURI(linesInfo.parStack[linesInfo.parStack.length - 1]),
167+
match
168+
})
169+
}
170+
return includes
159171
}
160172

161173
function ifInvalidFile(inc: IncludeObj, lines: string[], incStack: string[], diagnostics: Map<string, Diagnostic[]>) {
@@ -202,11 +214,9 @@ function mergeInclude(inc: IncludeObj, lines: string[], incStack: string[], diag
202214

203215
incStack.push(inc.path)
204216

205-
// TODO deal with the fact that includes may not be the sole text on a line
206217
// add #line indicating we are entering a new include block
207218
lines[inc.lineNumTopLevel] = `#line 0 "${formatURI(inc.path)}"`
208219
// merge the lines of the file into the current document
209-
// TODO do we wanna use a DLL here?
210220
lines.splice(inc.lineNumTopLevel + 1, 0, ...dataLines)
211221
// add the closing #line indicating we're re-entering a block a level up
212222
lines.splice(inc.lineNumTopLevel + 1 + dataLines.length, 0, `#line ${inc.lineNum + 1} "${inc.parent}"`)
@@ -248,21 +258,23 @@ function lint(docURI: string, lines: string[], includes: Map<string, IncludeObj>
248258
})
249259
}
250260

251-
function propogateDiagnostic(errorFile: string, type: string, line: string, msg: string, diagnostics: Map<string, Diagnostic[]>, includes: Map<string, IncludeObj>) {
252-
let nextFile = errorFile
253-
while (nextFile !== '0') {
254-
// TODO this doesnt deal with the fact that an include can have multiple parents :(
255-
const diag = {
261+
function propogateDiagnostic(errorFile: string, type: string, line: string, msg: string, diagnostics: Map<string, Diagnostic[]>, includes: Map<string, IncludeObj>, parentURI?: string) {
262+
includeGraph.get(parentURI || errorFile).parents.forEach((pair, parURI) => {
263+
console.log('parent', parURI, 'child', errorFile)
264+
const diag: Diagnostic = {
256265
severity: errorType(type),
257-
range: calcRange(includes.get(nextFile).lineNum, includes.get(nextFile).parent),
258-
message: `Line ${line} ${includes.get(errorFile).path.replace(conf.shaderpacksPath, '')} ${replaceWords(msg)}`,
266+
range: calcRange(pair.first, parURI),
267+
message: `Line ${line} ${errorFile.replace(conf.shaderpacksPath, '')} ${replaceWords(msg)}`,
259268
source: 'mc-glsl'
260269
}
261270

262-
diagnostics.get(includes.get(nextFile).parent).push(diag)
271+
if (!diagnostics.has(parURI)) diagnostics.set(parURI, [])
272+
diagnostics.get(parURI).push(diag)
263273

264-
nextFile = includes.get(nextFile).parent
265-
}
274+
if (pair.second.parents.size > 0) {
275+
propogateDiagnostic(errorFile, type, line, msg, diagnostics, includes, parURI)
276+
}
277+
})
266278
}
267279

268280
export const replaceWords = (msg: string) => Array.from(tokens.entries()).reduce((acc, [key, value]) => acc.replace(key, value), msg)

server/src/server.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ export function onEvent(document: vsclangproto.TextDocument) {
5555

5656
function lintBubbleDown(uri: string, document: vsclangproto.TextDocument) {
5757
includeGraph.get(uri).parents.forEach((parent, parentURI) => {
58-
console.log(parentURI)
59-
console.log(parent.parents)
60-
if (parent.parents.size > 0) {
58+
if (parent.second.parents.size > 0) {
6159
lintBubbleDown(parentURI, document)
6260
} else {
6361
const lines = getDocumentContents(parentURI).split('\n')

tslint.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
"severity": "warning"
3434
},
3535
"curly": [true, "ignore-same-line"],
36-
"whitespace": false
36+
"whitespace": false,
37+
"no-trailing-whitespace": {
38+
"severity": "warning"
39+
}
3740
}
3841
}

0 commit comments

Comments
 (0)