diff --git a/.gitignore b/.gitignore index 9b1ee42..9b3e627 100644 --- a/.gitignore +++ b/.gitignore @@ -118,7 +118,7 @@ out # Nuxt.js build / generate output .nuxt -dist + # Gatsby files diff --git a/bin/glslangValidatorLinux b/bin/glslangValidatorLinux new file mode 100755 index 0000000..f21fe54 Binary files /dev/null and b/bin/glslangValidatorLinux differ diff --git a/bin/glslangValidatorMac b/bin/glslangValidatorMac new file mode 100644 index 0000000..3ed3044 Binary files /dev/null and b/bin/glslangValidatorMac differ diff --git a/bin/glslangValidatorWindows.exe b/bin/glslangValidatorWindows.exe new file mode 100644 index 0000000..c90fd5e Binary files /dev/null and b/bin/glslangValidatorWindows.exe differ diff --git a/dist/constants.d.ts b/dist/constants.d.ts new file mode 100644 index 0000000..e02c5e6 --- /dev/null +++ b/dist/constants.d.ts @@ -0,0 +1,3 @@ +export declare const VERTEX_EXTS: string[]; +export declare const FRAGMENT_EXTS: string[]; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/constants.d.ts.map b/dist/constants.d.ts.map new file mode 100644 index 0000000..2de1c37 --- /dev/null +++ b/dist/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAyC,CAAC;AAClE,eAAO,MAAM,aAAa,UAAyC,CAAC"} \ No newline at end of file diff --git a/dist/constants.js b/dist/constants.js new file mode 100644 index 0000000..3c49f4f --- /dev/null +++ b/dist/constants.js @@ -0,0 +1,3 @@ +export const VERTEX_EXTS = ['vert', 'vs', 'vert.glsl', 'vs.glsl']; +export const FRAGMENT_EXTS = ['frag', 'fs', 'frag.glsl', 'fs.glsl']; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/constants.js.map b/dist/constants.js.map new file mode 100644 index 0000000..81ba0fd --- /dev/null +++ b/dist/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/error-manager.d.ts b/dist/error-manager.d.ts new file mode 100644 index 0000000..9785f10 --- /dev/null +++ b/dist/error-manager.d.ts @@ -0,0 +1,16 @@ +type ErrorData = { + line: number; + message: string; +}; +export declare class ErrorManager { + static checkSource(content: string, stage: string): Promise; + static getErrorData(row: string): { + line: number; + message: string; + }; + static getStageName(filePath: string): string; + static getLinesWithErrors(data: string): string[]; + static getPlatformName(): string; +} +export {}; +//# sourceMappingURL=error-manager.d.ts.map \ No newline at end of file diff --git a/dist/error-manager.d.ts.map b/dist/error-manager.d.ts.map new file mode 100644 index 0000000..8990166 --- /dev/null +++ b/dist/error-manager.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"error-manager.d.ts","sourceRoot":"","sources":["../src/error-manager.ts"],"names":[],"mappings":"AAMA,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qBAAa,YAAY;WACV,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAiC9E,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB;IAiBD,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAc7C,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAajD,MAAM,CAAC,eAAe,IAAI,MAAM;CAYjC"} \ No newline at end of file diff --git a/dist/error-manager.js b/dist/error-manager.js new file mode 100644 index 0000000..e47ee78 --- /dev/null +++ b/dist/error-manager.js @@ -0,0 +1,83 @@ +import * as path from 'path'; +import { platform } from 'os'; +import { Stream } from 'stream'; +import { exec } from 'child_process'; +import { FRAGMENT_EXTS, VERTEX_EXTS } from './constants'; +export class ErrorManager { + static async checkSource(content, stage) { + const platformName = this.getPlatformName(); + // Base is the path where this file is located + const base = path.resolve(__dirname, '..'); + const validatorPath = path.join(base, 'bin', `glslangValidator${platformName}`); + const result = exec(`${validatorPath} --stdin -C -S ${stage}`); + if (!result.stdout || !result.stdin) { + return []; + } + const errors = []; + // Handle errors from the validator + result.stdout.on('data', (data) => { + const linesWithErrors = this.getLinesWithErrors(data); + errors.push(...linesWithErrors.map(this.getErrorData)); + }); + // Stream the file content to the validator + const stdinStream = new Stream.Readable(); + stdinStream.push(content); + stdinStream.push(null); + stdinStream.pipe(result.stdin); + return new Promise((resolve) => { + result.on('close', () => { + resolve(errors); + }); + }); + } + static getErrorData(row) { + // Remove the error or warning prefix + if (row.startsWith('ERROR: 0:')) { + row = row.substring(9); + } + else if (row.startsWith('WARNING: 0:')) { + row = row.substring(11); + } + else { + return { line: -1, message: row }; + } + // Find the line number + const colonIndex = row.indexOf(':'); + const line = Number(row.substring(0, colonIndex)); + const message = row.substring(colonIndex + 1).trim(); + return { line, message }; + } + static getStageName(filePath) { + const [ext1, ext2] = path.extname(filePath).split('.'); + if (VERTEX_EXTS.includes(ext1) || VERTEX_EXTS.includes(ext2)) { + return 'vert'; + } + if (FRAGMENT_EXTS.includes(ext1) || FRAGMENT_EXTS.includes(ext2)) { + return 'frag'; + } + throw new Error('Unsupported file extension'); + } + static getLinesWithErrors(data) { + const rows = data.split('\n'); + const results = []; + for (const row of rows) { + if (row.startsWith('ERROR: ') || row.startsWith('WARNING: ')) { + results.push(row); + } + } + return results; + } + static getPlatformName() { + switch (platform()) { + case 'win32': + return 'Windows'; + case 'linux': + return 'Linux'; + case 'darwin': + return 'Mac'; + default: + throw new Error('Unsupported platform'); + } + } +} +//# sourceMappingURL=error-manager.js.map \ No newline at end of file diff --git a/dist/error-manager.js.map b/dist/error-manager.js.map new file mode 100644 index 0000000..3353943 --- /dev/null +++ b/dist/error-manager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"error-manager.js","sourceRoot":"","sources":["../src/error-manager.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/graph.d.ts b/dist/graph.d.ts new file mode 100644 index 0000000..99df986 --- /dev/null +++ b/dist/graph.d.ts @@ -0,0 +1,9 @@ +export declare class Graph { + private adjList; + constructor(); + addEdge(src: T, dest: T): void; + getNeighbors(node: T): T[]; + private dfs; + hasCycle(): boolean; +} +//# sourceMappingURL=graph.d.ts.map \ No newline at end of file diff --git a/dist/graph.d.ts.map b/dist/graph.d.ts.map new file mode 100644 index 0000000..591c42a --- /dev/null +++ b/dist/graph.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAClB,OAAO,CAAC,OAAO,CAAc;;IAM7B,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAU9B,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE;IAI1B,OAAO,CAAC,GAAG;IAuBX,QAAQ,IAAI,OAAO;CAYpB"} \ No newline at end of file diff --git a/dist/graph.js b/dist/graph.js new file mode 100644 index 0000000..77997c1 --- /dev/null +++ b/dist/graph.js @@ -0,0 +1,52 @@ +export class Graph { + constructor() { + Object.defineProperty(this, "adjList", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.adjList = new Map(); + } + addEdge(src, dest) { + const neighbors = this.adjList.get(src); + if (neighbors) { + neighbors.push(dest); + } + else { + this.adjList.set(src, [dest]); + } + } + getNeighbors(node) { + return this.adjList.get(node) || []; + } + dfs(node, visited, recStack) { + if (recStack.has(node)) { + return true; + } + if (visited.has(node)) { + return false; + } + visited.add(node); + recStack.add(node); + const neighbors = this.adjList.get(node) || []; + for (const neighbor of neighbors) { + if (this.dfs(neighbor, visited, recStack)) { + return true; + } + } + recStack.delete(node); + return false; + } + hasCycle() { + const visited = new Set(); + const recStack = new Set(); + for (const node of this.adjList.keys()) { + if (this.dfs(node, visited, recStack)) { + return true; + } + } + return false; + } +} +//# sourceMappingURL=graph.js.map \ No newline at end of file diff --git a/dist/graph.js.map b/dist/graph.js.map new file mode 100644 index 0000000..c7f2bac --- /dev/null +++ b/dist/graph.js.map @@ -0,0 +1 @@ +{"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,KAAK;IAGhB;QAFQ;;;;;WAAqB;QAG3B,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,GAAM,EAAE,IAAO;QACrB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,YAAY,CAAC,IAAO;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAEO,GAAG,CAAC,IAAO,EAAE,OAAe,EAAE,QAAgB;QACpD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEnB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ;QACN,MAAM,OAAO,GAAG,IAAI,GAAG,EAAK,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAK,CAAC;QAE9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACtC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"} \ No newline at end of file diff --git a/dist/import-resolver.d.ts b/dist/import-resolver.d.ts new file mode 100644 index 0000000..fc3c85a --- /dev/null +++ b/dist/import-resolver.d.ts @@ -0,0 +1,17 @@ +import { Graph } from './graph'; +export declare class ImportResolver { + private graph; + static resolve(filePath: string): Promise; + private reserverRootFileFunctions; + buildImportGraph(filePath: string): Promise>; + combineFiles(node: string, visited?: Set): Promise; + private fileId; + private fileIds; + private getFileId; + private reservedNames; + private getFunctionName; + private getImports; + getFileContent(filePath: string): Promise; + private getAbsolutePath; +} +//# sourceMappingURL=import-resolver.d.ts.map \ No newline at end of file diff --git a/dist/import-resolver.d.ts.map b/dist/import-resolver.d.ts.map new file mode 100644 index 0000000..4bb4ff1 --- /dev/null +++ b/dist/import-resolver.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"import-resolver.d.ts","sourceRoot":"","sources":["../src/import-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIhC,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA8B;WAE9B,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAQzC,yBAAyB;IAajC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAiB1D,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBnF,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAkC;IAEjD,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,UAAU;IAgBZ,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6FvD,OAAO,CAAC,eAAe;CAOxB"} \ No newline at end of file diff --git a/dist/import-resolver.js b/dist/import-resolver.js new file mode 100644 index 0000000..61fa9e7 --- /dev/null +++ b/dist/import-resolver.js @@ -0,0 +1,187 @@ +import path from 'path'; +import fs from 'fs/promises'; +import { Graph } from './graph'; +import { parser, generate } from '@onegl/glsl-parser'; +import { visit } from '@onegl/glsl-parser/ast'; +export class ImportResolver { + constructor() { + Object.defineProperty(this, "graph", { + enumerable: true, + configurable: true, + writable: true, + value: new Graph() + }); + Object.defineProperty(this, "fileId", { + enumerable: true, + configurable: true, + writable: true, + value: 1 + }); + Object.defineProperty(this, "fileIds", { + enumerable: true, + configurable: true, + writable: true, + value: new Map() + }); + Object.defineProperty(this, "reservedNames", { + enumerable: true, + configurable: true, + writable: true, + value: new Map() + }); + } + static async resolve(filePath) { + filePath = path.resolve(filePath); + const importGraph = new ImportResolver(); + await importGraph.buildImportGraph(filePath); + await importGraph.reserverRootFileFunctions(filePath); + return await importGraph.combineFiles(filePath); + } + async reserverRootFileFunctions(filePath) { + const content = await fs.readFile(filePath, 'utf-8'); + const ast = parser.parse(content); + visit(ast, { + function_header: { + enter: (path) => { + this.reservedNames.set(path.node.name.identifier, filePath); + }, + }, + }); + } + async buildImportGraph(filePath) { + const ast = parser.parse(await fs.readFile(filePath, 'utf-8')); + const neighbors = await this.getImports(ast, filePath).map((importData) => importData.importPath); + for (const neighbor of neighbors) { + this.graph.addEdge(filePath, neighbor); + if (this.graph.hasCycle()) { + throw new Error(`Cycle detected in import graph`); + } + await this.buildImportGraph(neighbor); + } + return this.graph; + } + async combineFiles(node, visited = new Set()) { + let output = ''; + if (visited.has(node)) { + return output; + } + visited.add(node); + const neighbors = this.graph.getNeighbors(node); + for (const neighbor of neighbors) { + output += await this.combineFiles(neighbor, visited); + } + output += await this.getFileContent(node); + return output; + } + getFileId(filePath) { + const fileId = this.fileIds.get(filePath); + if (fileId) { + return fileId; + } + this.fileIds.set(filePath, this.fileId); + return this.fileId++; + } + getFunctionName(functionName, functionOriginfilePath) { + const stem = path.basename(functionOriginfilePath, path.extname(functionOriginfilePath)); + const fileId = this.getFileId(functionOriginfilePath); + const uniqueName = `${stem}_${functionName}_${fileId}`; + const reservedBy = this.reservedNames.get(functionName); + if (reservedBy === undefined) { + this.reservedNames.set(functionName, functionOriginfilePath); + return functionName; + } + else if (reservedBy === functionOriginfilePath) { + return functionName; + } + return uniqueName; + } + getImports(ast, parentPath) { + const importNodes = ast.program.filter((node) => node.type === 'import_statement'); + return importNodes.map((node) => ({ + importName: node.name.identifier, + // TODO: Check the parser to see if we can fix this + importPath: this.getAbsolutePath(node.path, parentPath), + })); + } + async getFileContent(filePath) { + let content = await fs.readFile(filePath, 'utf-8'); + const ast = parser.parse(content); + const imports = this.getImports(ast, filePath); + visit(ast, { + function_call: { + enter: (path) => { + let importName; + let originalFunctionName; + if (path.node.type !== 'function_call') { + return; + } + if (path.node.identifier.type !== 'postfix') { + return; + } + const expression = path.node.identifier.expression; + const postfix = path.node.identifier.postfix; + // Check expression + if (expression.type !== 'type_specifier') { + return; + } + if (!('identifier' in expression.specifier)) { + return; + } + if (typeof expression.specifier.identifier !== 'string') { + return; + } + // Check postfix + if (postfix.type !== 'field_selection') { + return; + } + if (!('identifier' in postfix.selection)) { + return; + } + if (typeof postfix.selection.identifier !== 'string') { + return; + } + importName = expression.specifier.identifier; + originalFunctionName = postfix.selection.identifier; + const importPath = imports.find((importData) => importData.importName === importName)?.importPath; + if (!importPath) { + return; + } + const newFunctionName = this.getFunctionName(originalFunctionName, importPath); + path.replaceWith({ + type: 'function_call', + lp: path.node.lp, + rp: path.node.rp, + args: path.node.args, + identifier: { + type: 'type_specifier', + specifier: { + type: 'type_name', + identifier: newFunctionName, + whitespace: '', + }, + quantifier: null, + }, + }); + }, + }, + }); + // Rename function declarations + visit(ast, { + function_header: { + enter: (path) => { + const functionName = path.node.name.identifier; + const newFunctionName = this.getFunctionName(functionName, filePath); + path.node.name.identifier = newFunctionName; + }, + }, + }); + return generate(ast); + } + getAbsolutePath(filePath, parentPath) { + if (filePath.startsWith('.')) { + return path.resolve(path.dirname(parentPath), filePath); + } + return filePath; + } +} +//# sourceMappingURL=import-resolver.js.map \ No newline at end of file diff --git a/dist/import-resolver.js.map b/dist/import-resolver.js.map new file mode 100644 index 0000000..bc70ca5 --- /dev/null +++ b/dist/import-resolver.js.map @@ -0,0 +1 @@ +{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../src/import-resolver.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..bf840c9 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,3 @@ +export { ErrorManager } from './error-manager'; +export { ImportResolver } from './import-resolver'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map new file mode 100644 index 0000000..6aa5585 --- /dev/null +++ b/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..4847c08 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,23 @@ +export { ErrorManager } from './error-manager'; +export { ImportResolver } from './import-resolver'; +// import { ErrorManager } from './error-manager'; +// import { ImportResolver } from './import-resolver'; +// async function main() { +// const inputFilePath = './example/input.vert'; +// const output = await ImportResolver.resolve(inputFilePath); +// console.log('\n\n'); +// console.log(output); +// const erros = await ErrorManager.checkSource(output, 'vert'); +// // Erros has the line number and the message +// // We will take the output and modify the lines with errors to add the error message at the end +// const lines = output.split('\n'); +// for (const error of erros) { +// lines[error.line - 1] = `${lines[error.line - 1]} \x1b[31m${error.message}\x1b[0m`; +// } +// console.log('\n\n'); +// console.log(lines.join('\n')); +// // You can write the output to a file +// console.log('Errors:', erros); +// } +// main(); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..0695373 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,kDAAkD;AAClD,sDAAsD;AAEtD,0BAA0B;AAC1B,kDAAkD;AAClD,gEAAgE;AAChE,yBAAyB;AACzB,yBAAyB;AAEzB,kEAAkE;AAElE,iDAAiD;AACjD,oGAAoG;AAEpG,sCAAsC;AACtC,iCAAiC;AACjC,0FAA0F;AAC1F,MAAM;AAEN,yBAAyB;AACzB,mCAAmC;AAEnC,0CAA0C;AAC1C,mCAAmC;AACnC,IAAI;AAEJ,UAAU"} \ No newline at end of file diff --git a/dist/package.json b/dist/package.json new file mode 100644 index 0000000..b342ea6 --- /dev/null +++ b/dist/package.json @@ -0,0 +1,24 @@ +{ + "name": "glsl-imports", + "module": "index.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "rm -rf dist && tsc && cp package.json dist/package.json" + }, + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@onegl/glsl-parser": "git+https://github.com/OneGL/glsl-parser.git" + } +} diff --git a/example/folder/input3.glsl b/example/folder/input3.glsl index bce5b3e..22150f5 100644 --- a/example/folder/input3.glsl +++ b/example/folder/input3.glsl @@ -1,7 +1,7 @@ import input4 from "../otro/input4.glsl"; import input2 from "../input2.glsl"; -int add3() { +int add3(int a, int b) { input4.add4(); input2.add2(); return 3; diff --git a/example/input.glsl b/example/input.vert similarity index 75% rename from example/input.glsl rename to example/input.vert index 4982a90..01424c3 100644 --- a/example/input.glsl +++ b/example/input.vert @@ -2,9 +2,11 @@ import input2 from "./input2.glsl"; import input3 from "./folder/input3.glsl"; // This import is not used import input4 from "./otro/input4.glsl"; -int main() { +void main() { input2.add2(); input4.add4(); - vec3 v = input3.getVec3(); + float a = input2.add2(); + + input3.add3(1, 1); return 0; } diff --git a/package-lock.json b/package-lock.json index c72e517..7b14280 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "glsl-imports", "dependencies": { - "@shaderfrog/glsl-parser": "file:../glsl-parser" + "@onegl/glsl-parser": "git+https://github.com/OneGL/glsl-parser.git" }, "devDependencies": { "@types/bun": "latest" @@ -15,36 +15,18 @@ "typescript": "^5.0.0" } }, - "../glsl-parser": { + "../glsl-parser1": { + "extraneous": true + }, + "node_modules/@onegl/glsl-parser": { "name": "@shaderfrog/glsl-parser", "version": "3.2.2", + "resolved": "git+ssh://git@github.com/OneGL/glsl-parser.git#540e382c5cf61e03a0f6c54c46e5036fef2afc2b", "license": "ISC", - "devDependencies": { - "@babel/core": "^7.15.5", - "@babel/preset-env": "^7.15.6", - "@babel/preset-typescript": "^7.15.0", - "@swc/core": "^1.4.11", - "@swc/jest": "^0.2.36", - "@types/jest": "^27.0.2", - "@types/node": "^16.10.2", - "jest": "^29.7.0", - "peggy": "^1.2.0", - "prettier": "^2.1.2", - "ts-jest": "^29.1.2", - "ts-jest-resolver": "^2.0.1", - "typescript": "^5.3.3" - }, "engines": { "node": ">=16" } }, - "../glsl-parser1": { - "extraneous": true - }, - "node_modules/@shaderfrog/glsl-parser": { - "resolved": "../glsl-parser", - "link": true - }, "node_modules/@types/bun": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.1.2.tgz", diff --git a/package.json b/package.json index b6e4b0c..b342ea6 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,16 @@ "name": "glsl-imports", "module": "index.ts", "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "rm -rf dist && tsc && cp package.json dist/package.json" + }, "devDependencies": { "@types/bun": "latest" }, @@ -9,6 +19,6 @@ "typescript": "^5.0.0" }, "dependencies": { - "@shaderfrog/glsl-parser": "file:../glsl-parser" + "@onegl/glsl-parser": "git+https://github.com/OneGL/glsl-parser.git" } } diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..d6f3e8d --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,2 @@ +export const VERTEX_EXTS = ['vert', 'vs', 'vert.glsl', 'vs.glsl']; +export const FRAGMENT_EXTS = ['frag', 'fs', 'frag.glsl', 'fs.glsl']; diff --git a/src/error-manager.ts b/src/error-manager.ts new file mode 100644 index 0000000..89bd18d --- /dev/null +++ b/src/error-manager.ts @@ -0,0 +1,105 @@ +import * as path from 'path'; +import { platform } from 'os'; +import { Stream } from 'stream'; +import { exec } from 'child_process'; +import { FRAGMENT_EXTS, VERTEX_EXTS } from './constants'; + +type ErrorData = { + line: number; + message: string; +}; + +export class ErrorManager { + static async checkSource(content: string, stage: string): Promise { + const platformName = this.getPlatformName(); + + // Base is the path where this file is located + const base = path.resolve(__dirname, '..'); + const validatorPath = path.join(base, 'bin', `glslangValidator${platformName}`); + const result = exec(`${validatorPath} --stdin -C -S ${stage}`); + + if (!result.stdout || !result.stdin) { + return []; + } + + const errors: ErrorData[] = []; + + // Handle errors from the validator + result.stdout.on('data', (data: string) => { + const linesWithErrors = this.getLinesWithErrors(data); + errors.push(...linesWithErrors.map(this.getErrorData)); + }); + + // Stream the file content to the validator + const stdinStream = new Stream.Readable(); + stdinStream.push(content); + stdinStream.push(null); + stdinStream.pipe(result.stdin); + + return new Promise((resolve) => { + result.on('close', () => { + resolve(errors); + }); + }); + } + + static getErrorData(row: string): { + line: number; + message: string; + } { + // Remove the error or warning prefix + if (row.startsWith('ERROR: 0:')) { + row = row.substring(9); + } else if (row.startsWith('WARNING: 0:')) { + row = row.substring(11); + } else { + return { line: -1, message: row }; + } + + // Find the line number + const colonIndex = row.indexOf(':'); + const line = Number(row.substring(0, colonIndex)); + const message = row.substring(colonIndex + 1).trim(); + return { line, message }; + } + + static getStageName(filePath: string): string { + const [ext1, ext2] = path.extname(filePath).split('.'); + + if (VERTEX_EXTS.includes(ext1) || VERTEX_EXTS.includes(ext2)) { + return 'vert'; + } + + if (FRAGMENT_EXTS.includes(ext1) || FRAGMENT_EXTS.includes(ext2)) { + return 'frag'; + } + + throw new Error('Unsupported file extension'); + } + + static getLinesWithErrors(data: string): string[] { + const rows = data.split('\n'); + const results: string[] = []; + + for (const row of rows) { + if (row.startsWith('ERROR: ') || row.startsWith('WARNING: ')) { + results.push(row); + } + } + + return results; + } + + static getPlatformName(): string { + switch (platform()) { + case 'win32': + return 'Windows'; + case 'linux': + return 'Linux'; + case 'darwin': + return 'Mac'; + default: + throw new Error('Unsupported platform'); + } + } +} diff --git a/src/import-resolver.ts b/src/import-resolver.ts index 81a295f..5fdd90b 100644 --- a/src/import-resolver.ts +++ b/src/import-resolver.ts @@ -1,8 +1,8 @@ import path from 'path'; import fs from 'fs/promises'; import { Graph } from './graph'; -import { parser, generate } from '@shaderfrog/glsl-parser'; -import { visit, type ImportStatementNode, type Program } from '@shaderfrog/glsl-parser/ast'; +import { parser, generate } from '@onegl/glsl-parser'; +import { visit, type ImportStatementNode, type Program } from '@onegl/glsl-parser/ast'; export class ImportResolver { private graph: Graph = new Graph(); diff --git a/src/index.ts b/src/index.ts index 3466b3d..582e442 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,2 @@ -import { ImportResolver } from './import-resolver'; - -async function main() { - const inputFilePath = './example/input.glsl'; - const output = await ImportResolver.resolve(inputFilePath); - console.log("\n\n") - console.log(output); -} - -main(); +export { ErrorManager } from './error-manager'; +export { ImportResolver } from './import-resolver'; diff --git a/tsconfig.json b/tsconfig.json index 3a1e427..1c52d37 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,28 +1,37 @@ { "compilerOptions": { - // Enable latest features - "lib": ["ESNext", "DOM"], - "target": "ESNext", + "target": "ES2020", "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "rootDir": "./src", - // Bundler mode + /* Bundler mode */ "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + + /* Types */ + "declaration": true, + "declarationMap": true, + "sourceMap": true, - // Best practices + /* Linting */ "strict": true, - "skipLibCheck": true, + "noUnusedLocals": true, + "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "strictNullChecks": true, + "forceConsistentCasingInFileNames": true, - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } + /* Output */ + "outDir": "dist" + }, + "tsc-alias": { + "verbose": false, + "resolveFullPaths": true, + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/__tests__/*"] }