Skip to content

Commit 0b876dc

Browse files
author
Loïc Mangeonjean
committed
fix!: update code according to monaco update
1 parent e99a342 commit 0b876dc

19 files changed

+179
-385
lines changed

rollup.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export default rollup.defineConfig({
111111
'@babel/plugin-proposal-optional-chaining'
112112
],
113113
babelHelpers: 'bundled',
114-
exclude: /node_modules\/(?!monaco-languageclient|vscode-languageserver-types|vscode-languageclient)/
114+
exclude: /node_modules\/(?!vscode-languageserver-types|vscode-languageclient)/
115115
}),
116116
visualizer(),
117117
alias({

src/createLanguageClient.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { MessageReader, MessageWriter, Message, Event, DataCallback, Disposable, PartialMessageInfo } from 'vscode-jsonrpc'
22
import {
3-
MonacoLanguageClient, Middleware, ErrorHandler, IConnectionProvider, MessageTransports
4-
} from 'monaco-languageclient'
3+
Middleware, ErrorHandler, MessageTransports, BaseLanguageClient
4+
, LanguageClientOptions as BaseLanguageClientOptions
5+
} from 'vscode-languageclient'
56
import { InitializeParams, InitializeRequest } from 'vscode-languageserver-protocol'
67
import { LanguageClientId, LanguageClientOptions } from './languageClientOptions'
78
import { Infrastructure } from './infrastructure'
@@ -59,6 +60,20 @@ class MiddlewareMessageReader implements MessageReader {
5960
}
6061
}
6162

63+
interface IConnectionProvider {
64+
get(encoding: string): Promise<MessageTransports>
65+
}
66+
67+
export class MonacoLanguageClient extends BaseLanguageClient {
68+
constructor (id: string, name: string, clientOptions: BaseLanguageClientOptions, protected readonly connectionProvider: IConnectionProvider) {
69+
super(id, name, clientOptions)
70+
}
71+
72+
protected override createMessageTransports (encoding: string): Promise<MessageTransports> {
73+
return this.connectionProvider.get(encoding)
74+
}
75+
}
76+
6277
/**
6378
* Add some hacks on transform for:
6479
* - Fix paths on windows
@@ -143,10 +158,9 @@ async function createLanguageClient (
143158
}
144159
}
145160

146-
const client = new _MonacoLanguageClient({
147-
id: `${id}-languageclient`,
148-
name: `CodinGame ${id} Language Client`,
149-
clientOptions: {
161+
const client = new _MonacoLanguageClient(
162+
`${id}-languageclient`, `CodinGame ${id} Language Client`,
163+
{
150164
// use a language id as a document selector
151165
documentSelector,
152166
// disable the default error handler
@@ -155,11 +169,9 @@ async function createLanguageClient (
155169
synchronize,
156170
initializationOptions: allInitializationOptions
157171
},
158-
connectionProvider: new CGLSPConnectionProvider(id, infrastructure)
159-
})
160-
client.registerConfigurationFeatures()
161-
client.registerProgressFeatures()
162-
client.registerTextDocumentSaveFeatures()
172+
new CGLSPConnectionProvider(id, infrastructure)
173+
)
174+
client.registerProposedFeatures()
163175

164176
if (createAdditionalFeatures != null) {
165177
client.registerFeatures(await createAdditionalFeatures(client))

src/extensionConfiguration.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,10 @@
1-
import { loadConfigurationForExtension } from '@codingame/monaco-editor-wrapper/features/extensionConfigurations'
21
import { registerDefaultConfigurations } from '@codingame/monaco-editor-wrapper'
32
import { LanguageClientOptions } from './languageClientOptions'
43

54
/**
65
* Load the configuration schemas from vscode extensions
76
* @param forLanguageClientIds Load the extensions related to these language client ids
8-
* @param useMutualizedProxy The language server proxy is used, so we only need to load configurations for language servers which are not mutualized
97
*/
10-
export async function loadExtensionConfigurations (clientOptions: LanguageClientOptions[], useMutualizedProxy: boolean): Promise<void> {
11-
const extensionConfigurationToLoad = new Set<string>()
12-
for (const clientOption of clientOptions) {
13-
if (!clientOption.mutualizable || !useMutualizedProxy) {
14-
clientOption.vscodeExtensionIds?.forEach(extensionId => {
15-
extensionConfigurationToLoad.add(extensionId)
16-
})
17-
}
18-
}
19-
20-
await Promise.all(Array.from(extensionConfigurationToLoad).map(extensionId => loadConfigurationForExtension(extensionId)))
21-
8+
export async function loadExtensionConfigurations (clientOptions: LanguageClientOptions[]): Promise<void> {
229
registerDefaultConfigurations(clientOptions.map(clientOption => clientOption.defaultConfigurationOverride).filter(<T> (v: T): v is Exclude<T, null | undefined> => v != null))
2310
}

src/extensions.ts

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { monaco, registerTextModelContentProvider } from '@codingame/monaco-editor-wrapper'
2-
import {
3-
MonacoLanguageClient, DisposableCollection
4-
} from 'monaco-languageclient'
1+
import { monaco } from '@codingame/monaco-editor-wrapper'
2+
import { FileSystemProviderCapabilities, FileSystemProviderError, FileSystemProviderErrorCode, FileType, IFileSystemProviderWithFileReadWriteCapability, IStat, registerFileSystemOverlay } from '@codingame/monaco-vscode-files-service-override'
53
import { StaticFeature, FeatureState } from 'vscode-languageclient/lib/common/api'
64
import { DidSaveTextDocumentNotification, Disposable, DocumentSelector, Emitter, ServerCapabilities, TextDocumentSyncOptions } from 'vscode-languageserver-protocol'
75
import * as vscode from 'vscode'
6+
import { IDisposable } from 'monaco-editor'
7+
import { DisposableStore } from 'vscode/monaco'
88
import { willShutdownNotificationType, WillShutdownParams } from './customRequests'
99
import { Infrastructure } from './infrastructure'
1010
import { LanguageClientManager } from './languageClient'
11-
import { getServices } from './services'
11+
import { MonacoLanguageClient } from './createLanguageClient'
1212

1313
interface ResolvedTextDocumentSyncCapabilities {
1414
resolvedTextDocumentSync?: TextDocumentSyncOptions
@@ -31,7 +31,7 @@ export class InitializeTextDocumentFeature implements StaticFeature {
3131
const languageClient = this.languageClient
3232
async function saveFile (textDocument: vscode.TextDocument) {
3333
if (documentSelector != null && vscode.languages.match(documentSelector, textDocument) > 0 && textDocument.uri.scheme === 'file') {
34-
await infrastructure.saveFileContent?.(textDocument, vscode.TextDocumentSaveReason.Manual, languageClient)
34+
await infrastructure.saveFileContent?.(textDocument.uri, textDocument.getText(), languageClient)
3535

3636
// Always send notification even if the server doesn't support it (because csharp register the didSave feature too late)
3737
await languageClient.sendNotification(DidSaveTextDocumentNotification.type, {
@@ -53,7 +53,7 @@ export class InitializeTextDocumentFeature implements StaticFeature {
5353
}
5454
}
5555

56-
dispose (): void {
56+
clear (): void {
5757
this.didOpenTextDocumentDisposable?.dispose()
5858
}
5959
}
@@ -73,7 +73,78 @@ export class WillDisposeFeature implements StaticFeature {
7373
}
7474
}
7575

76-
dispose (): void {}
76+
clear (): void {}
77+
}
78+
79+
const encoder = new TextEncoder()
80+
const decoder = new TextDecoder()
81+
class InfrastructureTextFileSystemProvider implements IFileSystemProviderWithFileReadWriteCapability {
82+
capabilities = FileSystemProviderCapabilities.FileReadWrite | FileSystemProviderCapabilities.PathCaseSensitive | FileSystemProviderCapabilities.Readonly
83+
constructor (private infrastructure: Infrastructure, private languageClientManager: LanguageClientManager) {
84+
}
85+
86+
private cachedContent: Map<string, Promise<string | undefined>> = new Map()
87+
private async getFileContent (resource: monaco.Uri): Promise<string | undefined> {
88+
if (!this.cachedContent.has(resource.toString()) && resource.toString().includes('.')) {
89+
this.cachedContent.set(resource.toString(), this.infrastructure.getFileContent!(resource, this.languageClientManager))
90+
}
91+
return await this.cachedContent.get(resource.toString())
92+
}
93+
94+
async readFile (resource: monaco.Uri): Promise<Uint8Array> {
95+
if (!resource.toString().startsWith(this.infrastructure.rootUri)) {
96+
throw FileSystemProviderError.create('file not found', FileSystemProviderErrorCode.FileNotFound)
97+
}
98+
const content = await this.getFileContent(resource)
99+
return encoder.encode(content)
100+
}
101+
102+
async writeFile (): Promise<void> {
103+
throw FileSystemProviderError.create('not allowed', FileSystemProviderErrorCode.NoPermissions)
104+
}
105+
106+
onDidChangeCapabilities = new vscode.EventEmitter<never>().event
107+
onDidChangeFile = new vscode.EventEmitter<never>().event
108+
watch (): IDisposable {
109+
return {
110+
dispose () {}
111+
}
112+
}
113+
114+
async stat (resource: monaco.Uri): Promise<IStat> {
115+
if (!resource.toString().startsWith(this.infrastructure.rootUri)) {
116+
throw FileSystemProviderError.create('file not found', FileSystemProviderErrorCode.FileNotFound)
117+
}
118+
try {
119+
const content = await this.getFileContent(resource)
120+
if (content != null) {
121+
return {
122+
type: FileType.File,
123+
size: encoder.encode(content).length,
124+
mtime: Date.now(),
125+
ctime: Date.now()
126+
}
127+
}
128+
} catch (err) {
129+
throw FileSystemProviderError.create(err as Error, FileSystemProviderErrorCode.Unknown)
130+
}
131+
throw FileSystemProviderError.create('file not found', FileSystemProviderErrorCode.FileNotFound)
132+
}
133+
134+
async mkdir (): Promise<void> {
135+
}
136+
137+
async readdir () {
138+
return []
139+
}
140+
141+
delete (): Promise<void> {
142+
throw new Error('Method not implemented.')
143+
}
144+
145+
rename (): Promise<void> {
146+
throw new Error('Method not implemented.')
147+
}
77148
}
78149

79150
export class FileSystemFeature implements StaticFeature {
@@ -82,22 +153,27 @@ export class FileSystemFeature implements StaticFeature {
82153
constructor (private infrastructure: Infrastructure, private languageClientManager: LanguageClientManager) {}
83154

84155
private registerFileHandlers (): Disposable {
85-
const disposableCollection = new DisposableCollection()
86-
const infrastructure = this.infrastructure
87-
const languageClientManager = this.languageClientManager
88-
disposableCollection.push(registerTextModelContentProvider('file', {
89-
async provideTextContent (resource: monaco.Uri): Promise<monaco.editor.ITextModel | null> {
90-
return await infrastructure.getFileContent(resource, languageClientManager)
91-
}
92-
}))
93-
disposableCollection.push(getServices().workspace.registerSaveDocumentHandler({
94-
async saveTextContent (document, reason) {
95-
if (languageClientManager.isModelManaged(document) && document.uri.scheme === 'file') {
96-
await infrastructure.saveFileContent?.(document, reason, languageClientManager)
156+
const disposables = new DisposableStore()
157+
158+
// Register readonly file system overlay to access remote files
159+
if (this.infrastructure.getFileContent != null) {
160+
disposables.add(registerFileSystemOverlay(-1, new InfrastructureTextFileSystemProvider(this.infrastructure, this.languageClientManager)))
161+
}
162+
163+
if (this.infrastructure.saveFileContent != null) {
164+
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.Uri.parse(this.infrastructure.rootUri), '**/*'))
165+
disposables.add(watcher)
166+
const onFileChange = async (uri: vscode.Uri) => {
167+
if ((await vscode.workspace.fs.stat(uri)).type === vscode.FileType.File) {
168+
const content = await vscode.workspace.fs.readFile(uri)
169+
await this.infrastructure.saveFileContent?.(uri, decoder.decode(content), this.languageClientManager)
97170
}
98171
}
99-
}))
100-
return disposableCollection
172+
watcher.onDidChange(onFileChange)
173+
watcher.onDidCreate(onFileChange)
174+
}
175+
176+
return disposables
101177
}
102178

103179
fillClientCapabilities (): void {}
@@ -117,4 +193,8 @@ export class FileSystemFeature implements StaticFeature {
117193
this.disposable?.dispose()
118194
this.disposable = undefined
119195
}
196+
197+
clear (): void {
198+
this.dispose()
199+
}
120200
}

src/extensions/cobol.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { MonacoLanguageClient } from 'monaco-languageclient'
2-
import { ProtocolRequestType } from 'vscode-languageclient/lib/common/api'
3-
import { DocumentSelector, ServerCapabilities } from 'vscode-languageserver-protocol'
1+
import { ProtocolRequestType, DocumentSelector, ServerCapabilities } from 'vscode-languageserver-protocol'
42
import * as vscode from 'vscode'
53
import { ExtensionFeature } from './tools'
4+
import { MonacoLanguageClient } from '../createLanguageClient'
65

76
export const ResolveCobolSubroutineRequestType = new ProtocolRequestType<string, string | undefined, never, void, void>('cobol/resolveSubroutine')
87
export class CobolResolveSubroutineFeature extends ExtensionFeature {

src/extensions/csharp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { MonacoLanguageClient } from 'monaco-languageclient'
21
import { Uri, ExtensionContext, workspace, CancellationToken } from 'vscode'
32
import { ProtocolRequestType } from 'vscode-languageserver-protocol'
43
import { ExtensionFeature } from './tools'
4+
import { MonacoLanguageClient } from '../createLanguageClient'
55

66
const OmnisharpMetadataRequestType = new ProtocolRequestType<{
77
Timeout: number

src/extensions/java.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { MonacoLanguageClient } from 'monaco-languageclient'
21
import { commands, Uri, languages, ExtensionContext, workspace, CancellationToken } from 'vscode'
32
import { Position as LSPosition, Location as LSLocation } from 'vscode-languageclient'
43
import { JavaInlayHintsProvider } from 'extensions/java/inlayHintsProvider'
@@ -7,6 +6,7 @@ import { Commands } from 'extensions/java/commands'
76
import { applyWorkspaceEdit } from 'extensions/java/extension'
87
import { ClassFileContentsRequest } from 'extensions/java/protocol'
98
import { ExtensionFeature } from './tools'
9+
import { MonacoLanguageClient } from '../createLanguageClient'
1010

1111
export class JavaExtensionFeature extends ExtensionFeature {
1212
constructor (private languageClient: MonacoLanguageClient) {

src/extensions/tools.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import { ExtensionContext } from 'vscode'
32
import { FeatureState, StaticFeature } from 'vscode-languageclient/lib/browser/main'
43
import { Disposable, DocumentSelector, ServerCapabilities } from 'vscode-languageserver-protocol'
@@ -46,6 +45,8 @@ class SimpleExtensionContext implements ExtensionContext, Disposable {
4645
get logPath () { return unsupported() }
4746
get extensionMode () { return unsupported() }
4847
get extension () { return unsupported() }
48+
get extensionRuntime () { return unsupported() }
49+
messagePassingProtocol = undefined
4950
}
5051

5152
export abstract class ExtensionFeature implements StaticFeature {
@@ -64,7 +65,7 @@ export abstract class ExtensionFeature implements StaticFeature {
6465

6566
protected abstract activate (context: ExtensionContext, capabilities: ServerCapabilities, documentSelector: DocumentSelector): void
6667

67-
dispose (): void {
68+
clear (): void {
6869
this.context.dispose()
6970
}
7071
}

src/hacks.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import { initializePromise } from '@codingame/monaco-editor-wrapper'
12
import * as monaco from 'monaco-editor'
23

3-
monaco.editor.onWillDisposeModel(model => {
4+
void initializePromise.then(() => {
5+
monaco.editor.onWillDisposeModel(model => {
46
// We need to do it in a timeout or else the marker change event is delayed
5-
setTimeout(() => {
6-
monaco.editor.setModelMarkers(model, 'default', [])
7+
setTimeout(() => {
8+
monaco.editor.setModelMarkers(model, 'default', [])
9+
})
710
})
811
})

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MessageTransports } from 'monaco-languageclient'
1+
import { MessageTransports } from 'vscode-languageclient'
22
import 'proxy-polyfill'
33
import type { WorkspaceFolder } from 'vscode'
44
import { CodinGameInfrastructure, Infrastructure } from './infrastructure'

0 commit comments

Comments
 (0)