Added regexes from old linter

Added LinterState to keep track of current lint run
Added the adding of include directive and finding top levels
This commit is contained in:
Noah Santschi-Cooney 2019-10-06 18:40:17 +01:00
parent d7d8f9de96
commit c28d23a971
4 changed files with 125 additions and 34 deletions

View file

@ -1,4 +1,86 @@
import { Diagnostic } from 'vscode-languageserver'
import * as vsclangproto from 'vscode-languageserver-protocol'
import { ConfigProvider } from './config'
import { Graph } from './graph'
import { linterLog } from './logging'
import { URI } from './uri'
// global include tree
const includeTree = new Graph()
const include = '#extension GL_GOOGLE_include_directive : require'
const reDiag = /^(ERROR|WARNING): ([^?<>*|"]+?):(\d+): (?:'.*?' : )?(.+)\r?/
const reVersion = /#version [\d]{3}/
const reInclude = /^(?:\s)*?(?:#include) "(.+)"\r?/
const reIncludeExt = /#extension GL_GOOGLE_include_directive ?: ?require/
interface LinterState {
hadIncludeDirective: boolean
eventDocument: vsclangproto.TextDocument
lines: string[]
diagnostics: Map<String, Diagnostic>
topLevelFiles: string[]
}
export class Linter {
private state: LinterState = {
hadIncludeDirective: true,
eventDocument: undefined,
diagnostics: new Map(),
lines: [],
topLevelFiles: [],
}
constructor(document: vsclangproto.TextDocument) {
this.state.eventDocument = document
this.state.lines = document.getText().split('\n')
}
public static do(document: vsclangproto.TextDocument, config: ConfigProvider) {
const uri = URI.fromFileURI(document.uri)
linterLog.info(`running linter for ${uri}`)
const linter = new Linter(document)
linter.gatherTopLevelFiles(uri, uri)
linter.addIncludeDirective()
linterLog.debug(`top level files for ${URI.trimShaderpacksPath(uri, config.config.shaderpacksPath)}: ` + JSON.stringify(linter.state.topLevelFiles))
}
private addIncludeDirective() {
if (this.state.lines.findIndex(x => reIncludeExt.test(x)) > -1) {
linterLog.debug('include directive found')
this.state.hadIncludeDirective = true
return
}
let hasDirective = true
linterLog.debug('include directive not found')
for (let i = 0; i < this.state.lines.length; i++) {
const line = this.state.lines[i]
if (reVersion.test(line)) {
linterLog.debug('found version on line ' + (i + 1))
this.state.lines.splice(i + 1, 0, include)
break
}
}
return
}
private gatherTopLevelFiles(uri: string, original: string): boolean {
if(includeTree.get(uri).parents.size == 0) {
// we've hit a parent with no further parents, add to top level files
if(uri != original) this.state.topLevelFiles.push(uri)
return false
}
includeTree.get(uri).parents.forEach((parent, parentURI) => {
this.gatherTopLevelFiles(parentURI, original)
})
return true
}
}

View file

@ -6,7 +6,7 @@ const defaultOpts = {
levels: ['debug', 'info', 'warn', 'error']
}
export const glslProviderLog = new Logger('glslangProvider')
export const glslProviderLog = new Logger('glslang')
glslProviderLog.appenders.set('std-log', defaultOpts)
export const linterLog = new Logger('linter')

View file

@ -2,8 +2,9 @@ import * as vsclang from 'vscode-languageserver'
import * as vsclangproto from 'vscode-languageserver-protocol'
import { completions } from './completionProvider'
import { ConfigProvider } from './config'
import { getDocumentLinks } from './linksProvider'
import { GLSLangProvider } from './glslangValidator'
import { getDocumentLinks } from './linksProvider'
import { Linter } from './linter'
const reVersion = /#version [\d]{3}/
@ -49,8 +50,11 @@ documents.onDidClose((event) => {
export function lint(document: vsclangproto.TextDocument) {
if (!glslangValidator.testExecutable()) {
glslangValidator.promptDownload()
return
}
Linter.do(document, configProvider)
/*
let sanitizedPath = conf.shaderpacksPath.replace(dirname(conf.shaderpacksPath), '')
if (sanitizedPath.startsWith('/shaderpacks') || glslangReady) return

View file

@ -1,4 +1,4 @@
import { uriLog as log } from './logging'
import { uriLog as log, uriLog } from './logging'
export function formatURI(uri: string): string {
const drive = uri[7]
@ -7,40 +7,45 @@ export function formatURI(uri: string): string {
}
export class URI {
public static fromFileURI(uri: string): string {
log.debug(`normalizing ${uri}`)
if (URI.isNormalized(uri)) {
log.debug(`already normalized ${uri}`)
return uri
public static trimShaderpacksPath(uri: string, path: string): string {
uriLog.debug(`replacing ${path} in ${uri}`)
return uri.replace(path, '')
}
public static fromFileURI(uri: string): string {
log.debug(`normalizing ${uri}`)
if (URI.isNormalized(uri)) {
log.debug(`already normalized ${uri}`)
return uri
}
// TODO windows
return uri.replace(/^file:\/\//, '').replace(/\\/, '/')
}
public static toFileURI(uri: string): string {
let fileURI = uri
if (!fileURI.startsWith('file:///')) {
if (/^\\[a-zA-Z]/.test(fileURI)) {
fileURI = 'file:///' + fileURI.substr(1)
} else if (fileURI.startsWith('/')) {
fileURI = 'file://' + fileURI
}
// TODO windows
return uri.replace(/^file:\/\//, '').replace(/\\/, '/')
} else if (fileURI.startsWith('file://\\')) {
fileURI = fileURI.replace('file://\\', 'file:///')
} else if (/^file:\/\/[a-zA-Z]/.test(fileURI)) {
fileURI = fileURI.replace('file://', 'file:///')
}
public static toFileURI(uri: string): string {
let fileURI = uri
log.debug(`formatted '${uri}' to '${fileURI}'`)
return fileURI
}
if (!fileURI.startsWith('file:///')) {
if (/^\\[a-zA-Z]/.test(fileURI)) {
fileURI = 'file:///' + fileURI.substr(1)
} else if (fileURI.startsWith('/')) {
fileURI = 'file://' + fileURI
}
} else if (fileURI.startsWith('file://\\')) {
fileURI = fileURI.replace('file://\\', 'file:///')
} else if (/^file:\/\/[a-zA-Z]/.test(fileURI)) {
fileURI = fileURI.replace('file://', 'file:///')
}
log.debug(`formatted '${uri}' to '${fileURI}'`)
return fileURI
private static isNormalized(uri: string): boolean {
if (uri.startsWith('file://') || uri.includes('%3A')) {
return false
}
private static isNormalized(uri: string): boolean {
if (uri.startsWith('file://') || uri.includes('%3A')) {
return false
}
return true
}
return true
}
}