Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend file system provider interface #1784

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -40,7 +40,7 @@
"vitest": "~1.5.0"
},
"overrides": {
"@types/node": "~16.18.41"
"@types/node": "^18.0.0"
},
"volta": {
"node": "18.19.1",
Expand Down
40 changes: 37 additions & 3 deletions packages/langium/src/node/node-file-system-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,51 @@ export class NodeFileSystemProvider implements FileSystemProvider {

encoding: NodeTextEncoding = 'utf-8';

exists(uri: URI): Promise<boolean> {
return new Promise(resolve => {
fs.stat(uri.fsPath, err => {
resolve(!err);
});
});
}

existsSync(uri: URI): boolean {
return fs.existsSync(uri.fsPath);
}

readBinary(uri: URI): Promise<Uint8Array> {
return fs.promises.readFile(uri.fsPath);
}

readBinarySync(uri: URI): Uint8Array {
return fs.readFileSync(uri.fsPath);
}

readFile(uri: URI): Promise<string> {
return fs.promises.readFile(uri.fsPath, this.encoding);
}

async readDirectory(folderPath: URI): Promise<FileSystemNode[]> {
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<FileSystemNode[]> {
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)
}));
}
}
Expand Down
54 changes: 54 additions & 0 deletions packages/langium/src/workspace/file-system-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>;
/**
* 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<Uint8Array>;
/**
* 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<string>;
/**
* 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<FileSystemNode[]>;
/**
* 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<boolean> {
return false;
}

existsSync(): boolean {
return false;
}

readBinary(): Promise<Uint8Array> {
throw new Error('No file system is available.');
}

readBinarySync(): Uint8Array {
throw new Error('No file system is available.');
}

readFile(): Promise<string> {
throw new Error('No file system is available.');
}

readFileSync(): string {
throw new Error('No file system is available.');
}

async readDirectory(): Promise<FileSystemNode[]> {
return [];
}

readDirectorySync(): FileSystemNode[] {
return [];
}

}

export const EmptyFileSystem = {
Expand Down
21 changes: 20 additions & 1 deletion packages/langium/test/workspace/document-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -708,6 +708,25 @@ class MockFileSystemProvider implements FileSystemProvider {
return Promise.resolve('');
}

async exists(_uri: URI): Promise<boolean> {
return false;
}
existsSync(): boolean {
return false;
}
async readBinary(_uri: URI): Promise<Uint8Array> {
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([]);
Expand Down
Loading