Linting of all currently discovered files that contain the edited include at some depth is pretty much working! Issue #11 highlights the blocking bug

This commit is contained in:
Noah Santschi-Cooney 2018-07-25 00:43:07 +01:00
parent 5e6a12c88b
commit 5a06d8ff1b
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
3 changed files with 58 additions and 30 deletions

View file

@ -4,7 +4,7 @@ import { execSync } from 'child_process'
import * as path from 'path'
import { readFileSync, existsSync } from 'fs'
import { conf } from './config'
import { postError, formatURI } from './utils'
import { postError, formatURI, getDocumentContents } from './utils'
import { platform } from 'os'
const reDiag = /^(ERROR|WARNING): ([^?<>*|"]+?):(\d+): (?:'.*?' : )?(.+)\r?/
@ -21,7 +21,7 @@ const filters = [
/Could not process include directive for header name:/
]
const includeToParent = new Map<string, string[]>()
export const includeToParent = new Map<string, Set<string>>()
type IncludeObj = {
lineNum: number,
@ -79,7 +79,8 @@ export function isInComment(line: string, state: Comment): Comment {
}
export function preprocess(lines: string[], docURI: string) {
if (lines.find((value: string, i: number, obj: string[]): boolean => reIncludeExt.test(value)) == undefined) {
// wish there was an ignore keyword like Go
if (lines.find((value: string, _, __): boolean => reIncludeExt.test(value)) == undefined) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
if (reVersion.test(line)) {
@ -93,17 +94,19 @@ export function preprocess(lines: string[], docURI: string) {
}
}
const incStack = [docURI]
const allIncludes: IncludeObj[] = []
const diagnostics = new Map<string, Diagnostic[]>()
processIncludes(lines, incStack, allIncludes, diagnostics)
processIncludes(lines, [docURI], allIncludes, diagnostics)
const includeMap = new Map<string, IncludeObj>(allIncludes.map(obj => [obj.path, obj]) as [string, IncludeObj][])
try {
lint(docURI, lines, includeMap, diagnostics)
} catch (e) {
postError(e)
}
}
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)
}
function processIncludes(lines: string[], incStack: string[], allIncludes: IncludeObj[], diagnostics: Map<string, Diagnostic[]>) {
@ -111,6 +114,7 @@ function processIncludes(lines: string[], incStack: string[], allIncludes: Inclu
allIncludes.push(...includes)
if (includes.length > 0) {
includes.reverse().forEach(inc => {
buildIncludeTree(inc)
mergeInclude(inc, lines, incStack, diagnostics)
})
// recursively check for more includes to be merged
@ -223,7 +227,8 @@ 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),
range: calcRange(includes.get(nextFile).lineNum - 1, includes.get(nextFile).parent),
// TODO put -1 back when #11 is sorted
range: calcRange(includes.get(nextFile).lineNum, includes.get(nextFile).parent),
message: includes.get(file).path.replace(conf.shaderpacksPath, '') + replaceWords(msg),
source: 'mc-glsl'
}
@ -253,14 +258,10 @@ const filterMatches = (output: string) => output
.filter(match => match && match.length === 5)
function calcRange(lineNum: number, uri: string): Range {
let lines = []
// TODO better error handling maybe?
if (documents.keys().includes('file://' + uri)) {
lines = documents.get('file://' + uri).getText().split('\n')
} else {
lines = readFileSync(uri).toString().split('\n')
}
const lines = getDocumentContents(uri).split('\n')
console.log(uri, lineNum, lines.length)
console.log(lines.slice(Math.max(lineNum - 3, 0), lineNum + 3).join('\n'))
const line = lines[lineNum]
const startOfLine = line.length - line.trimLeft().length

View file

@ -1,14 +1,16 @@
import * as vsclang from 'vscode-languageserver'
import * as vsclangproto from 'vscode-languageserver-protocol'
import { completions } from './completionProvider'
import { preprocess, ext } from './linter'
import { preprocess, ext, includeToParent } from './linter'
import { extname } from 'path'
const reVersion = /#version [\d]{3}/
export let connection: vsclang.IConnection
connection = vsclang.createConnection(new vsclang.IPCMessageReader(process), new vsclang.IPCMessageWriter(process))
import { onConfigChange } from './config'
import { formatURI } from './utils'
import { formatURI, postError, getDocumentContents } from './utils'
export const documents = new vsclang.TextDocuments()
documents.listen(connection)
@ -36,15 +38,34 @@ documents.onDidClose((event) => connection.sendDiagnostics({uri: event.document.
//documents.onDidChangeContent(onEvent)
export function onEvent(document: vsclangproto.TextDocument) {
if (!ext.has(extname(document.uri))) return
try {
console.log(document.uri)
console.log(formatURI(document.uri))
preprocess(document.getText().split('\n'), formatURI(document.uri))
} catch (e) {
connection.window.showErrorMessage(`[mc-glsl] ${e.message}`)
throw(e)
const uri = formatURI(document.uri)
if (includeToParent.has(uri)) {
lintBubbleDown(uri, document)
return
}
if (!ext.has(extname(document.uri))) return
try {
preprocess(document.getText().split('\n'), uri)
} catch (e) {
postError(e)
}
}
function lintBubbleDown(uri: string, document: vsclangproto.TextDocument) {
includeToParent.get(uri).forEach(parent => {
console.log(`${uri} has parent ${parent}`)
if (includeToParent.has(parent)) {
lintBubbleDown(parent, document)
} else {
const lines = getDocumentContents(parent).split('\n')
if (lines.filter(l => reVersion.test(l)).length > 0) {
console.log(`${parent} is at top, linting down`)
preprocess(lines, parent)
}
}
})
}
connection.onDidChangeConfiguration(onConfigChange)

View file

@ -1,4 +1,5 @@
import { connection } from './server'
import { connection, documents } from './server'
import { readFileSync } from 'fs'
export function postError(e: Error) {
connection.window.showErrorMessage(e.message)
@ -6,3 +7,8 @@ export function postError(e: Error) {
}
export const formatURI = (uri: string) => uri.replace(/^file:\/\//, '').replace(/^(?:\/)c%3A/, 'C:').replace(/\\/g, '/')
export function getDocumentContents(uri: string): string {
if (documents.keys().includes('file://' + uri)) return documents.get('file://' + uri).getText()
else return readFileSync(uri).toString()
}