mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-07-12 13:55:43 +00:00
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:
parent
d7d8f9de96
commit
c28d23a971
4 changed files with 125 additions and 34 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue