Recursive includes works 90%!!!!! Wrong line numbers are given because its basing the line numbers off the root file

This commit is contained in:
Noah Santschi-Cooney 2018-07-02 18:56:17 +01:00
parent d2e58f475d
commit d7a5adb668
3 changed files with 58 additions and 60 deletions

2
.vscode/launch.json vendored
View file

@ -11,7 +11,7 @@
"stopOnEntry": false, "stopOnEntry": false,
"sourceMaps": true, "sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/**/*.js"], "outFiles": ["${workspaceRoot}/client/out/**/*.js"],
"preLaunchTask": "watch" "preLaunchTask": "watch",
}, },
{ {
"type": "node", "type": "node",

View file

@ -1,7 +1,7 @@
import { conf, connection, documents, checkBinary } from './server' import { conf, connection, documents } from './server'
import './global' import './global'
import { TextDocument, Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver' import { TextDocument, Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'
import { exec } from 'child_process' import { execSync } from 'child_process'
import * as path from 'path' import * as path from 'path'
import { readFileSync } from 'fs' import { readFileSync } from 'fs'
@ -52,9 +52,8 @@ const tokens: {[key: string]: string} = {
'RIGHT_BRACE': '}' 'RIGHT_BRACE': '}'
} }
export function preprocess(document: TextDocument, topLevel: boolean, incStack: string[]) { // TODO exclude exts not in ext
const lines = document.getText().split('\n') export function preprocess(lines: string[], docURI: string, topLevel: boolean, incStack: string[]) {
const docURI = formatURI(document.uri)
if (topLevel) { if (topLevel) {
let inComment = false let inComment = false
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
@ -84,13 +83,20 @@ export function preprocess(document: TextDocument, topLevel: boolean, incStack:
lines.splice(inc.lineNum + 1 + addedLines + i, 0, ...dataLines) lines.splice(inc.lineNum + 1 + addedLines + i, 0, ...dataLines)
addedLines += dataLines.length addedLines += dataLines.length
lines.splice(inc.lineNum + 1 + addedLines + i, 0, `#line ${inc.lineNum} "${docURI}"`) lines.splice(inc.lineNum + 1 + addedLines + i, 0, `#line ${inc.lineNum} "${docURI}"`)
preprocess(lines, incPath, false, incStack)
}) })
} }
console.log(lines.join('\n'))
lint(docURI, lines, includes) if (!topLevel) return
//console.log(lines.join('\n'))
try {
lint(docURI, lines, includes)
} catch (e) {
}
} }
const formatURI = (uri: string) => uri.replace(/^file:\/\//, '') export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '')
//TODO not include in comments //TODO not include in comments
const getIncludes = (lines: string[]) => lines const getIncludes = (lines: string[]) => lines
@ -107,45 +113,43 @@ function absPath(currFile: string, includeFile: string): string {
if (includeFile.charAt(0) === '/') { if (includeFile.charAt(0) === '/') {
const shaderPath = currFile.replace(conf.shaderpacksPath, '').split('/').slice(0, 3).join('/') const shaderPath = currFile.replace(conf.shaderpacksPath, '').split('/').slice(0, 3).join('/')
return path.join(conf.shaderpacksPath, shaderPath, includeFile) return path.join(conf.shaderpacksPath, shaderPath, includeFile)
} else {
const shaderPath = path.dirname(currFile)
return path.join(shaderPath, includeFile)
} }
return path.join(path.dirname(currFile), includeFile)
} }
function lint(uri: string, lines: string[], includes: {lineNum: number, match: RegExpMatchArray}[]) { function lint(uri: string, lines: string[], includes: {lineNum: number, match: RegExpMatchArray}[]) {
checkBinary( console.log(lines.join('\n'))
() => { let out: string = ''
const child = exec(`${conf.glslangPath} --stdin -S ${ext[path.extname(uri)]}`, (error, out) => { try {
const diagnostics: {[uri: string]: Diagnostic[]} = {} execSync(`${conf.glslangPath} --stdin -S ${ext[path.extname(uri)]}`, {input: lines.join('\n')})
diagnostics[uri] = [] } catch (e) {
includes.forEach(obj => { out = e.stdout.toString()
diagnostics[absPath(uri, obj.match[1])] = [] }
})
const matches = filterMatches(out) as RegExpMatchArray[] const diagnostics: {[uri: string]: Diagnostic[]} = {}
matches.forEach((match) => { diagnostics[uri] = []
const [whole, type, file, line, msg] = match includes.forEach(obj => {
const diag = { diagnostics[absPath(uri, obj.match[1])] = []
severity: type === 'ERROR' ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning, })
range: calcRange(parseInt(line) - 1, uri),
message: replaceWord(msg),
source: 'mc-glsl'
}
diagnostics[file].push(diag)
})
daigsArray(diagnostics).forEach(d => { const matches = filterMatches(out)
connection.sendDiagnostics({uri: 'file://' + d.uri, diagnostics: d.diag}) matches.forEach((match) => {
}) const [whole, type, file, line, msg] = match
}) const diag = {
lines.forEach(line => child.stdin.write(line)) severity: type === 'ERROR' ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning,
child.stdin.end() range: calcRange(parseInt(line) - 1, uri),
message: replaceWord(msg),
source: 'mc-glsl'
} }
) diagnostics[file ? uri : file].push(diag)
})
daigsArray(diagnostics).forEach(d => {
connection.sendDiagnostics({uri: d.uri, diagnostics: d.diag})
})
} }
const daigsArray = (diags: {[uri: string]: Diagnostic[]}) => Object.keys(diags).map(uri => ({uri, diag: diags[uri]})) const daigsArray = (diags: {[uri: string]: Diagnostic[]}) => Object.keys(diags).map(uri => ({uri: 'file://' + uri, diag: diags[uri]}))
const filterMatches = (output: string) => output const filterMatches = (output: string) => output
.split('\n') .split('\n')

View file

@ -1,9 +1,9 @@
import * as vsclang from 'vscode-languageserver' import * as vsclang from 'vscode-languageserver'
import { TextDocumentChangeEvent } from 'vscode-languageserver-protocol' import { TextDocumentChangeEvent, TextDocument } from 'vscode-languageserver-protocol'
import { Config } from './config' import { Config } from './config'
import { completions } from './completionProvider' import { completions } from './completionProvider'
import { preprocess, ext } from './linter' import { preprocess, ext, formatURI } from './linter'
import { exec } from 'child_process' import { exec, execSync } from 'child_process'
import { extname } from 'path' import { extname } from 'path'
export const connection = vsclang.createConnection(new vsclang.IPCMessageReader(process), new vsclang.IPCMessageWriter(process)) export const connection = vsclang.createConnection(new vsclang.IPCMessageReader(process), new vsclang.IPCMessageWriter(process))
@ -26,33 +26,27 @@ connection.onInitialize((params): vsclang.InitializeResult => {
connection.onExit(() => {}) connection.onExit(() => {})
documents.onDidOpen(onEvent) documents.onDidOpen((event) => onEvent(event.document))
documents.onDidSave(onEvent) documents.onDidSave((event) => onEvent(event.document))
//documents.onDidChangeContent(onEvent) //documents.onDidChangeContent(onEvent)
function onEvent(event: TextDocumentChangeEvent) { function onEvent(document: TextDocument) {
preprocess(event.document, true, [event.document.uri.replace(/^file:\/\//, '')]) preprocess(document.getText().split('\n'), formatURI(document.uri), true, [document.uri.replace(/^file:\/\//, '')])
}
export function checkBinary(ok: () => void, fail?: () => any) {
exec(conf.glslangPath, (error) => {
if (error['code'] !== 1) {
if (fail) fail()
return
}
ok()
})
} }
connection.onDidChangeConfiguration((change) => { connection.onDidChangeConfiguration((change) => {
const temp = change.settings.mcglsl as Config const temp = change.settings.mcglsl as Config
conf = new Config(temp['shaderpacksPath'], temp['glslangValidatorPath']) conf = new Config(temp['shaderpacksPath'], temp['glslangValidatorPath'])
checkBinary( try {
() => {documents.all().forEach(document => preprocess(document, true, [document.uri.replace(/^file:\/\//, '')]))}, execSync(conf.glslangPath)
() => {connection.window.showErrorMessage(`[mc-glsl] glslangValidator not found at: ${conf.glslangPath}`)} documents.all().forEach(document => onEvent(document))
) } catch (e) {
if (e.status !== 1) {
connection.window.showErrorMessage(`[mc-glsl] glslangValidator not found at: '${conf.glslangPath}' or returned non-0 code`)
}
}
}) })
connection.onCompletion((textDocumentPosition: vsclang.TextDocumentPositionParams) => completions) connection.onCompletion((textDocumentPosition: vsclang.TextDocumentPositionParams) => completions)