mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-08-28 12:34:16 +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 {
|
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']
|
levels: ['debug', 'info', 'warn', 'error']
|
||||||
}
|
}
|
||||||
|
|
||||||
export const glslProviderLog = new Logger('glslangProvider')
|
export const glslProviderLog = new Logger('glslang')
|
||||||
glslProviderLog.appenders.set('std-log', defaultOpts)
|
glslProviderLog.appenders.set('std-log', defaultOpts)
|
||||||
|
|
||||||
export const linterLog = new Logger('linter')
|
export const linterLog = new Logger('linter')
|
||||||
|
|
|
@ -2,8 +2,9 @@ import * as vsclang from 'vscode-languageserver'
|
||||||
import * as vsclangproto from 'vscode-languageserver-protocol'
|
import * as vsclangproto from 'vscode-languageserver-protocol'
|
||||||
import { completions } from './completionProvider'
|
import { completions } from './completionProvider'
|
||||||
import { ConfigProvider } from './config'
|
import { ConfigProvider } from './config'
|
||||||
import { getDocumentLinks } from './linksProvider'
|
|
||||||
import { GLSLangProvider } from './glslangValidator'
|
import { GLSLangProvider } from './glslangValidator'
|
||||||
|
import { getDocumentLinks } from './linksProvider'
|
||||||
|
import { Linter } from './linter'
|
||||||
|
|
||||||
const reVersion = /#version [\d]{3}/
|
const reVersion = /#version [\d]{3}/
|
||||||
|
|
||||||
|
@ -49,8 +50,11 @@ documents.onDidClose((event) => {
|
||||||
|
|
||||||
export function lint(document: vsclangproto.TextDocument) {
|
export function lint(document: vsclangproto.TextDocument) {
|
||||||
if (!glslangValidator.testExecutable()) {
|
if (!glslangValidator.testExecutable()) {
|
||||||
|
glslangValidator.promptDownload()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Linter.do(document, configProvider)
|
||||||
/*
|
/*
|
||||||
let sanitizedPath = conf.shaderpacksPath.replace(dirname(conf.shaderpacksPath), '')
|
let sanitizedPath = conf.shaderpacksPath.replace(dirname(conf.shaderpacksPath), '')
|
||||||
if (sanitizedPath.startsWith('/shaderpacks') || glslangReady) return
|
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 {
|
export function formatURI(uri: string): string {
|
||||||
const drive = uri[7]
|
const drive = uri[7]
|
||||||
|
@ -7,40 +7,45 @@ export function formatURI(uri: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class URI {
|
export class URI {
|
||||||
public static fromFileURI(uri: string): string {
|
public static trimShaderpacksPath(uri: string, path: string): string {
|
||||||
log.debug(`normalizing ${uri}`)
|
uriLog.debug(`replacing ${path} in ${uri}`)
|
||||||
if (URI.isNormalized(uri)) {
|
return uri.replace(path, '')
|
||||||
log.debug(`already normalized ${uri}`)
|
}
|
||||||
return uri
|
|
||||||
|
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
|
} else if (fileURI.startsWith('file://\\')) {
|
||||||
return uri.replace(/^file:\/\//, '').replace(/\\/, '/')
|
fileURI = fileURI.replace('file://\\', 'file:///')
|
||||||
|
} else if (/^file:\/\/[a-zA-Z]/.test(fileURI)) {
|
||||||
|
fileURI = fileURI.replace('file://', 'file:///')
|
||||||
}
|
}
|
||||||
|
|
||||||
public static toFileURI(uri: string): string {
|
log.debug(`formatted '${uri}' to '${fileURI}'`)
|
||||||
let fileURI = uri
|
return fileURI
|
||||||
|
}
|
||||||
|
|
||||||
if (!fileURI.startsWith('file:///')) {
|
private static isNormalized(uri: string): boolean {
|
||||||
if (/^\\[a-zA-Z]/.test(fileURI)) {
|
if (uri.startsWith('file://') || uri.includes('%3A')) {
|
||||||
fileURI = 'file:///' + fileURI.substr(1)
|
return false
|
||||||
} 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 {
|
return true
|
||||||
if (uri.startsWith('file://') || uri.includes('%3A')) {
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue