diff --git a/package-lock.json b/package-lock.json index 1656a45ef..2f9934868 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "examples/statemachine" ], "devDependencies": { - "@types/node": "~16.18.41", + "@types/node": "^18.0.0", "@types/vscode": "~1.67.0", "@typescript-eslint/eslint-plugin": "~6.4.1", "@typescript-eslint/parser": "~6.4.1", @@ -1764,9 +1764,13 @@ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" }, "node_modules/@types/node": { - "version": "16.18.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.68.tgz", - "integrity": "sha512-sG3hPIQwJLoewrN7cr0dwEy+yF5nD4D/4FxtQpFciRD/xwUzgD+G05uxZHv5mhfXo4F9Jkp13jjn0CC2q325sg==" + "version": "18.19.70", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.70.tgz", + "integrity": "sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", @@ -9936,6 +9940,12 @@ "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, + "packages/generator-langium/node_modules/@types/node": { + "version": "16.18.123", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.123.tgz", + "integrity": "sha512-/n7I6V/4agSpJtFDKKFEa763Hc1z3hmvchobHS1TisCOTKD5nxq8NJ2iK7SRIMYL276Q9mgWOx2AWp5n2XI6eA==", + "license": "MIT" + }, "packages/generator-langium/node_modules/@types/which": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.3.tgz", diff --git a/package.json b/package.json index 4c8ce7aa8..92e64be79 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "reset:repo": "git clean -f -X -d" }, "devDependencies": { - "@types/node": "~16.18.41", + "@types/node": "^18.0.0", "@types/vscode": "~1.67.0", "@typescript-eslint/eslint-plugin": "~6.4.1", "@typescript-eslint/parser": "~6.4.1", @@ -40,7 +40,7 @@ "vitest": "~1.5.0" }, "overrides": { - "@types/node": "~16.18.41" + "@types/node": "^18.0.0" }, "volta": { "node": "18.19.1", diff --git a/packages/langium/src/node/node-file-system-provider.ts b/packages/langium/src/node/node-file-system-provider.ts index 740929a23..05d139b07 100644 --- a/packages/langium/src/node/node-file-system-provider.ts +++ b/packages/langium/src/node/node-file-system-provider.ts @@ -15,17 +15,51 @@ export class NodeFileSystemProvider implements FileSystemProvider { encoding: NodeTextEncoding = 'utf-8'; + exists(uri: URI): Promise { + return new Promise(resolve => { + fs.stat(uri.fsPath, err => { + resolve(!err); + }); + }); + } + + existsSync(uri: URI): boolean { + return fs.existsSync(uri.fsPath); + } + + readBinary(uri: URI): Promise { + return fs.promises.readFile(uri.fsPath); + } + + readBinarySync(uri: URI): Uint8Array { + return fs.readFileSync(uri.fsPath); + } + readFile(uri: URI): Promise { return fs.promises.readFile(uri.fsPath, this.encoding); } - async readDirectory(folderPath: URI): Promise { - const dirents = await fs.promises.readdir(folderPath.fsPath, { withFileTypes: true }); + readFileSync(uri: URI): string { + return fs.readFileSync(uri.fsPath, this.encoding); + } + + async readDirectory(uri: URI): Promise { + const dirents = await fs.promises.readdir(uri.fsPath, { withFileTypes: true }); + return dirents.map(dirent => ({ + dirent, // Include the raw entry, it may be useful... + isFile: dirent.isFile(), + isDirectory: dirent.isDirectory(), + uri: UriUtils.joinPath(uri, dirent.name) + })); + } + + readDirectorySync(uri: URI): FileSystemNode[] { + const dirents = fs.readdirSync(uri.fsPath, { withFileTypes: true }); return dirents.map(dirent => ({ dirent, // Include the raw entry, it may be useful... isFile: dirent.isFile(), isDirectory: dirent.isDirectory(), - uri: UriUtils.joinPath(folderPath, dirent.name) + uri: UriUtils.joinPath(uri, dirent.name) })); } } diff --git a/packages/langium/src/workspace/file-system-provider.ts b/packages/langium/src/workspace/file-system-provider.ts index 0c7a58d6c..70373ddaa 100644 --- a/packages/langium/src/workspace/file-system-provider.ts +++ b/packages/langium/src/workspace/file-system-provider.ts @@ -18,28 +18,82 @@ export type FileSystemFilter = (node: FileSystemNode) => boolean; * Provides methods to interact with an abstract file system. The default implementation is based on the node.js `fs` API. */ export interface FileSystemProvider { + /** + * Checks if a file exists at the specified URI. + * @returns `true` if a file exists at the specified URI, `false` otherwise. + */ + exists(uri: URI): Promise; + /** + * Checks if a file exists at the specified URI synchronously. + * @returns `true` if a file exists at the specified URI, `false` otherwise. + */ + existsSync(uri: URI): boolean; + /** + * Reads a binary file asynchronously from a given URI. + * @returns The binary content of the file with the specified URI. + */ + readBinary(uri: URI): Promise; + /** + * Reads a binary file synchronously from a given URI. + * @returns The binary content of the file with the specified URI. + */ + readBinarySync(uri: URI): Uint8Array; /** * Reads a document asynchronously from a given URI. * @returns The string content of the file with the specified URI. */ readFile(uri: URI): Promise; + /** + * Reads a document synchronously from a given URI. + * @returns The string content of the file with the specified + */ + readFileSync(uri: URI): string; /** * Reads the directory information for the given URI. * @returns The list of file system entries that are contained within the specified directory. */ readDirectory(uri: URI): Promise; + /** + * Reads the directory information for the given URI synchronously. + * @returns The list of file system entries that are contained within the specified directory. + */ + readDirectorySync(uri: URI): FileSystemNode[]; } export class EmptyFileSystemProvider implements FileSystemProvider { + async exists(): Promise { + return false; + } + + existsSync(): boolean { + return false; + } + + readBinary(): Promise { + throw new Error('No file system is available.'); + } + + readBinarySync(): Uint8Array { + throw new Error('No file system is available.'); + } + readFile(): Promise { throw new Error('No file system is available.'); } + readFileSync(): string { + throw new Error('No file system is available.'); + } + async readDirectory(): Promise { return []; } + readDirectorySync(): FileSystemNode[] { + return []; + } + } export const EmptyFileSystem = { diff --git a/packages/langium/test/workspace/document-builder.test.ts b/packages/langium/test/workspace/document-builder.test.ts index 1241bb44e..3e1d1e531 100644 --- a/packages/langium/test/workspace/document-builder.test.ts +++ b/packages/langium/test/workspace/document-builder.test.ts @@ -4,7 +4,7 @@ * terms of the MIT License, which is available in the project root. ******************************************************************************/ -import type { AstNode, DocumentBuilder, FileSystemProvider, LangiumDocument, LangiumDocumentFactory, LangiumDocuments, Module, Reference, ValidationChecks } from 'langium'; +import type { AstNode, DocumentBuilder, FileSystemNode, FileSystemProvider, LangiumDocument, LangiumDocumentFactory, LangiumDocuments, Module, Reference, ValidationChecks } from 'langium'; import { AstUtils, DocumentState, TextDocument, URI, isOperationCancelled, startCancelableOperation } from 'langium'; import { createServicesForGrammar } from 'langium/grammar'; import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest'; @@ -708,6 +708,25 @@ class MockFileSystemProvider implements FileSystemProvider { return Promise.resolve(''); } + async exists(_uri: URI): Promise { + return false; + } + existsSync(): boolean { + return false; + } + async readBinary(_uri: URI): Promise { + return new Uint8Array(); + } + readBinarySync(_uri: URI): Uint8Array { + return new Uint8Array(); + } + readFileSync(_uri: URI): string { + return ''; + } + readDirectorySync(_uri: URI): FileSystemNode[] { + return []; + } + // Return an empty array for any directory readDirectory(_uri: URI): Promise<[]> { return Promise.resolve([]);