@@ -2,7 +2,7 @@ import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'
22import { connection , documents } from './server'
33import { execSync } from 'child_process'
44import * as path from 'path'
5- import { readFileSync , existsSync } from 'fs'
5+ import { readFileSync , existsSync , statSync , Stats } from 'fs'
66import { conf } from './config'
77import { postError , formatURI , getDocumentContents } from './utils'
88import { platform } from 'os'
@@ -11,7 +11,7 @@ import { Comment } from './comment'
1111
1212const reDiag = / ^ ( E R R O R | W A R N I N G ) : ( [ ^ ? < > * | " ] + ?) : ( \d + ) : (?: ' .* ?' : ) ? ( .+ ) \r ? /
1313const reVersion = / # v e r s i o n [ \d ] { 3 } /
14- const reInclude = / ^ (?: \s ) * ?(?: # i n c l u d e ) " ( (?: \/ ? [ ^ ? < > : * | " ] + ? ) + ? \. (?: [ a - z A - Z ] + ? ) ) " \r ? /
14+ const reInclude = / ^ (?: \s ) * ?(?: # i n c l u d e ) " ( . + ) " \r ? /
1515const reIncludeExt = / # e x t e n s i o n G L _ G O O G L E _ i n c l u d e _ d i r e c t i v e ? : ? r e q u i r e /
1616const include = '#extension GL_GOOGLE_include_directive : require'
1717const win = platform ( ) === 'win32'
@@ -25,7 +25,6 @@ const filters = [
2525
2626export const includeGraph = new Graph ( )
2727
28- export const includeToParent = new Map < string , Set < string > > ( )
2928export const allFiles = new Set < string > ( )
3029
3130type IncludeObj = {
@@ -99,17 +98,14 @@ export function preprocess(lines: string[], docURI: string) {
9998 lint ( docURI , lines , includeMap , diagnostics )
10099}
101100
102- function buildIncludeTree ( inc : IncludeObj ) {
103- if ( ! includeToParent . has ( inc . path ) ) includeToParent . set ( inc . path , new Set ( [ inc . parent ] ) )
104- else includeToParent . get ( inc . path ) . add ( inc . parent )
105- }
101+ const buildIncludeGraph = ( inc : IncludeObj ) => includeGraph . setParent ( inc . path , inc . parent )
106102
107103function processIncludes ( lines : string [ ] , incStack : string [ ] , allIncludes : IncludeObj [ ] , diagnostics : Map < string , Diagnostic [ ] > , hasDirective : boolean ) {
108104 const includes = getIncludes ( incStack [ 0 ] , lines )
109105 allIncludes . push ( ...includes )
110106 if ( includes . length > 0 ) {
111107 includes . reverse ( ) . forEach ( inc => {
112- buildIncludeTree ( inc )
108+ buildIncludeGraph ( inc )
113109 mergeInclude ( inc , lines , incStack , diagnostics , hasDirective )
114110 } )
115111 // recursively check for more includes to be merged
@@ -162,24 +158,40 @@ export function getIncludes(uri: string, lines: string[]) {
162158 } , [ ] )
163159}
164160
161+ function ifInvalidFile ( inc : IncludeObj , lines : string [ ] , incStack : string [ ] , diagnostics : Map < string , Diagnostic [ ] > ) {
162+ const range = calcRange ( inc . lineNumTopLevel - ( win ? 1 : 0 ) , incStack [ 0 ] )
163+ diagnostics . set (
164+ inc . parent ,
165+ [
166+ ...( diagnostics . get ( inc . parent ) || [ ] ) ,
167+ {
168+ severity : DiagnosticSeverity . Error ,
169+ range,
170+ message : `${ inc . path . replace ( conf . shaderpacksPath , '' ) } is missing or an invalid file.` ,
171+ source : 'mc-glsl'
172+ }
173+ ]
174+ )
175+ lines [ inc . lineNumTopLevel ] = ''
176+ }
177+
165178function mergeInclude ( inc : IncludeObj , lines : string [ ] , incStack : string [ ] , diagnostics : Map < string , Diagnostic [ ] > , hasDirective : boolean ) {
166- if ( ! existsSync ( inc . path ) ) {
167- const range = calcRange ( inc . lineNumTopLevel - ( win ? 1 : 0 ) , incStack [ 0 ] )
168- diagnostics . set (
169- inc . parent ,
170- [
171- ...( diagnostics . get ( inc . parent ) || [ ] ) ,
172- {
173- severity : DiagnosticSeverity . Error ,
174- range,
175- message : `${ inc . path . replace ( conf . shaderpacksPath , '' ) } is missing.` ,
176- source : 'mc-glsl'
177- }
178- ]
179- )
180- lines [ inc . lineNumTopLevel ] = ''
179+ let stats : Stats
180+ try {
181+ stats = statSync ( inc . path )
182+ } catch ( e ) {
183+ if ( e . code === 'ENOENT' ) {
184+ ifInvalidFile ( inc , lines , incStack , diagnostics )
185+ return
186+ }
187+ throw e
188+ }
189+
190+ if ( ! stats . isFile ( ) ) {
191+ ifInvalidFile ( inc , lines , incStack , diagnostics )
181192 return
182193 }
194+
183195 const dataLines = readFileSync ( inc . path ) . toString ( ) . split ( '\n' )
184196
185197 // if the includes parent is the top level (aka where the include directive is placed)
@@ -230,7 +242,6 @@ function lint(uri: string, lines: string[], includes: Map<string, IncludeObj>, d
230242 // TODO what if we dont know the top level parent? Feel like thats a non-issue given that we have uri
231243 diag = {
232244 severity : errorType ( type ) ,
233- // TODO put -1 back when #11 is sorted
234245 range : calcRange ( includes . get ( nextFile ) . lineNum , includes . get ( nextFile ) . parent ) ,
235246 message : `Line ${ line } ${ includes . get ( file ) . path . replace ( conf . shaderpacksPath , '' ) } ${ replaceWords ( msg ) } ` ,
236247 source : 'mc-glsl'
0 commit comments