Skip to content

Commit 92b5d7f

Browse files
author
Loïc Mangeonjean
committed
fix: use a filesystem overlay to capture file write event sooner
1 parent a676e29 commit 92b5d7f

File tree

1 file changed

+55
-16
lines changed

1 file changed

+55
-16
lines changed

src/extensions.ts

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { DidSaveTextDocumentNotification, Disposable, DocumentSelector, Emitter,
55
import * as vscode from 'vscode'
66
import { IDisposable } from 'monaco-editor'
77
import { DisposableStore } from 'vscode/monaco'
8-
import { willShutdownNotificationType, WillShutdownParams } from './customRequests'
9-
import { Infrastructure } from './infrastructure'
10-
import { LanguageClientManager } from './languageClient'
8+
import { URI } from 'vscode/vscode/vs/base/common/uri'
119
import { MonacoLanguageClient } from './createLanguageClient'
10+
import { LanguageClientManager } from './languageClient'
11+
import { Infrastructure } from './infrastructure'
12+
import { willShutdownNotificationType, WillShutdownParams } from './customRequests'
1213

1314
async function bufferToBase64 (buffer: ArrayBuffer | Uint8Array) {
1415
// use a FileReader to generate a base64 data URI:
@@ -95,6 +96,51 @@ export class WillDisposeFeature implements StaticFeature {
9596
clear (): void {}
9697
}
9798

99+
class InfrastructureFileSystemUpdaterProvider implements IFileSystemProviderWithFileReadWriteCapability {
100+
capabilities = FileSystemProviderCapabilities.FileReadWrite | FileSystemProviderCapabilities.PathCaseSensitive
101+
constructor (private infrastructure: Infrastructure, private languageClientManager: LanguageClientManager) {
102+
}
103+
104+
readFile (): Promise<Uint8Array> {
105+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
106+
}
107+
108+
async writeFile (resource: URI, content: Uint8Array): Promise<void> {
109+
await this.infrastructure.writeFile!(resource, await bufferToBase64(content), this.languageClientManager)
110+
111+
throw FileSystemProviderError.create('File written, continue', FileSystemProviderErrorCode.FileNotFound)
112+
}
113+
114+
onDidChangeCapabilities = new vscode.EventEmitter<never>().event
115+
onDidChangeFile = new vscode.EventEmitter<never>().event
116+
onDidWatchError = new vscode.EventEmitter<never>().event
117+
watch (): IDisposable {
118+
return {
119+
dispose () {}
120+
}
121+
}
122+
123+
stat (): Promise<IStat> {
124+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
125+
}
126+
127+
async mkdir (): Promise<void> {
128+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
129+
}
130+
131+
readdir (): Promise<[string, FileType][]> {
132+
throw FileSystemProviderError.create('Not found', FileSystemProviderErrorCode.FileNotFound)
133+
}
134+
135+
delete (): Promise<void> {
136+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
137+
}
138+
139+
rename (): Promise<void> {
140+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
141+
}
142+
}
143+
98144
class InfrastructureFileSystemProvider implements IFileSystemProviderWithFileReadWriteCapability {
99145
capabilities = FileSystemProviderCapabilities.FileReadWrite | FileSystemProviderCapabilities.PathCaseSensitive | FileSystemProviderCapabilities.Readonly
100146
constructor (private infrastructure: Infrastructure, private languageClientManager: LanguageClientManager) {
@@ -158,6 +204,7 @@ class InfrastructureFileSystemProvider implements IFileSystemProviderWithFileRea
158204
}
159205

160206
async mkdir (): Promise<void> {
207+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
161208
}
162209

163210
async readdir (resource: monaco.Uri) {
@@ -177,11 +224,11 @@ class InfrastructureFileSystemProvider implements IFileSystemProviderWithFileRea
177224
}
178225

179226
delete (): Promise<void> {
180-
throw new Error('Method not implemented.')
227+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
181228
}
182229

183230
rename (): Promise<void> {
184-
throw new Error('Method not implemented.')
231+
throw FileSystemProviderError.create('Not allowed', FileSystemProviderErrorCode.NoPermissions)
185232
}
186233
}
187234

@@ -193,22 +240,14 @@ export class FileSystemFeature implements StaticFeature {
193240
private registerFileHandlers (): Disposable {
194241
const disposables = new DisposableStore()
195242

196-
// Register readonly file system overlay to access remote files
197243
if (this.infrastructure.readFile != null) {
244+
// Register a readonly file system overlay to access remote files
198245
disposables.add(registerFileSystemOverlay(-1, new InfrastructureFileSystemProvider(this.infrastructure, this.languageClientManager)))
199246
}
200247

201248
if (this.infrastructure.writeFile != null) {
202-
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.Uri.parse(this.infrastructure.rootUri), '**/*'))
203-
disposables.add(watcher)
204-
const onFileChange = async (uri: vscode.Uri) => {
205-
if ((await vscode.workspace.fs.stat(uri)).type === vscode.FileType.File) {
206-
const content = await vscode.workspace.fs.readFile(uri)
207-
await this.infrastructure.writeFile?.(uri, await bufferToBase64(content), this.languageClientManager)
208-
}
209-
}
210-
watcher.onDidChange(onFileChange)
211-
watcher.onDidCreate(onFileChange)
249+
// register another filesystem to capture file write with a higher priority
250+
disposables.add(registerFileSystemOverlay(1, new InfrastructureFileSystemUpdaterProvider(this.infrastructure, this.languageClientManager)))
212251
}
213252

214253
return disposables

0 commit comments

Comments
 (0)