Skip to content

Files ​

Servers know files by URI and want to hear when files change, appear, move or go. The package converts paths, matches changes against what a server watches and sends the notifications. Watching the disk and changing files stay with the app.

Paths and URIs ​

pathToFileUri(path) makes a file: URI of a POSIX or Windows path, escaping each segment. fileUriToPath(uri) goes back, or returns null for another scheme. Neither checks that a path is inside the project.

ts
import { fileUriToPath, pathToFileUri } from '@adecore/lsp';

pathToFileUri('/work/my file.ts'); // 'file:///work/my%20file.ts'
fileUriToPath('file:///work/my%20file.ts'); // '/work/my file.ts'
fileUriToPath('untitled:Untitled-1'); // null

Make every URI with pathToFileUri, so one file never shows up under two spellings.

Watched files ​

session.watchedFiles() returns the watchers the server registered. watchesFile(watchers, root, path, type) says whether a change concerns them. type is a FileChangeType: 1 created, 2 changed or 3 deleted. Send matches with session.didChangeWatchedFiles(changes).

ts
import { pathToFileUri, watchesFile } from '@adecore/lsp';

disk.onChange((path, type) => {
    if (watchesFile(session.watchedFiles(), '/work', path, type)) {
        void session.didChangeWatchedFiles([{ uri: pathToFileUri(path), type }]);
    }
});

disk stands for the app's own watcher. A path in node_modules, vendor or .git only matches a pattern that names that folder.

File operations ​

When a person renames, creates or deletes a file, a server may want to update other files first, such as the imports that point at a moved file. The session has a will and a did method for each operation:

OperationMethodsEntries
RenamewillRenameFiles, didRenameFilesRenamedFile (oldUri, newUri, directory)
CreatewillCreateFiles, didCreateFilesCreatedFile (uri, directory)
DeletewillDeleteFiles, didDeleteFilesDeletedFile (uri, directory)

A will method returns the server's WorkspaceEdit, or null. Apply it as any other workspace edit before the files change, then call the did method. A server asked before a delete expects the files to still exist.

ts
const files = [{ oldUri: pathToFileUri(from), newUri: pathToFileUri(to), directory: false }];
const edit = await session.willRenameFiles(files);

if (edit !== null) {
    await applyEdit(edit);
}

await moveFile(from, to);
await session.didRenameFiles(files);

applyEdit and moveFile stand for the app's own steps. The session sends only the files the server's filters accept. fileOperationFilters(operation) returns those filters, for a host that wants to check first.

Licenses and third-party notices are listed in each package.