Skip to content

Commit

Permalink
feat: poll lsp status & support close LSP server
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanba committed Feb 4, 2024
1 parent 5f470f6 commit 198707e
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 90 deletions.
2 changes: 1 addition & 1 deletion packages/libro-lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
"@difizen/libro-kernel": "^0.1.18",
"@difizen/libro-prompt-cell": "^0.1.18",
"@difizen/libro-terminal": "^0.1.18",
"@difizen/libro-lsp": "^0.1.18",
"@difizen/libro-toc": "^0.1.18",
"@difizen/libro-cofine-editor-core": "^0.1.18",
"@difizen/libro-language-client": "^0.1.18",
"@difizen/mana-app": "latest",
"@difizen/mana-common": "latest",
"@difizen/mana-react": "latest",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { LibroKernelManager, LibroSessionManager } from '@difizen/libro-kernel';
import type { ILanguageServerManager, TLanguageServerId } from '@difizen/libro-lsp';
import { ILSPDocumentConnectionManager } from '@difizen/libro-lsp';
import { LibroLanguageClientManager } from '@difizen/libro-language-client';
import { TerminalCommands, TerminalManager } from '@difizen/libro-terminal';
import {
BaseView,
Expand Down Expand Up @@ -35,8 +34,7 @@ const PanelRender: React.FC = () => {
libroKernelManager,
libroSessionManager,
terminalManager,
lspManager,
lspConnectionManager,
libroLanguageClientManager,
commandRegistry,
} = instance;

Expand All @@ -48,23 +46,18 @@ const PanelRender: React.FC = () => {
LibroPanelCollapseItem[] | undefined
>();

// const lspManager = useInject<ILSPDocumentConnectionManager>(
// DocumentConnectionManager,
// ).languageServerManager;

const [lspItems, setLSPItems] = useState<LibroPanelCollapseItem[] | undefined>();

lspManager.sessionsChanged(() => {
const sessions = lspManager.sessions;
libroLanguageClientManager.sessionsChanged(() => {
const sessions = libroLanguageClientManager.sessions;

const items = [] as LibroPanelCollapseItem[];

sessions.forEach((session: any, key: string) => {
items.push({
id: key,
name: `${key} (${session.spec.languages.join('/')})`,
shutdown: async () =>
await lspConnectionManager.disconnectServer(key as TLanguageServerId),
shutdown: async () => await libroLanguageClientManager.closeLanguageClient(key),
});
});

Expand Down Expand Up @@ -173,7 +166,9 @@ const PanelRender: React.FC = () => {
<LibroCollapse
type={LibroPanelCollapseItemType.LSP}
items={lspItems}
shutdownAll={async () => await lspConnectionManager.disconnectAllServers()}
shutdownAll={async () =>
await libroLanguageClientManager.closeAllLanguageClient()
}
/>
</div>
);
Expand All @@ -191,16 +186,15 @@ export class KernelAndTerminalPanelView extends BaseView {
libroKernelManager: LibroKernelManager;
libroSessionManager: LibroSessionManager;
terminalManager: TerminalManager;
lspConnectionManager: ILSPDocumentConnectionManager;
lspManager: ILanguageServerManager;
libroLanguageClientManager: LibroLanguageClientManager;
commandRegistry: CommandRegistry;

constructor(
@inject(LibroKernelManager) libroKernelManager: LibroKernelManager,
@inject(LibroSessionManager) libroSessionManager: LibroSessionManager,
@inject(TerminalManager) terminalManager: TerminalManager,
@inject(ILSPDocumentConnectionManager)
lspDocumentConnectionManager: ILSPDocumentConnectionManager,
@inject(LibroLanguageClientManager)
libroLanguageClientManager: LibroLanguageClientManager,
@inject(CommandRegistry) commandRegistry: CommandRegistry,
) {
super();
Expand All @@ -210,8 +204,7 @@ export class KernelAndTerminalPanelView extends BaseView {
this.libroKernelManager = libroKernelManager;
this.libroSessionManager = libroSessionManager;
this.terminalManager = terminalManager;
this.lspConnectionManager = lspDocumentConnectionManager;
this.lspManager = lspDocumentConnectionManager.languageServerManager;
this.libroLanguageClientManager = libroLanguageClientManager;
this.commandRegistry = commandRegistry;
}

Expand All @@ -224,6 +217,6 @@ export class KernelAndTerminalPanelView extends BaseView {
refresh() {
this.libroSessionManager.refreshRunning();
this.terminalManager.refreshRunning();
this.lspManager.refreshRunning();
this.libroLanguageClientManager.refreshRunning();
}
}
8 changes: 1 addition & 7 deletions packages/libro-language-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,19 @@
"@difizen/libro-kernel": "^0.1.10",
"@difizen/libro-common": "^0.1.10",
"@difizen/libro-lsp": "^0.1.10",
"@difizen/libro-code-editor": "^0.1.10",
"@difizen/mana-app": "latest",
"@difizen/mana-common": "latest",
"lodash.mergewith": "^4.6.2",
"uuid": "^9.0.0",
"@difizen/vscode-languageserver-protocol": "^3.17.6-next.2",
"vscode-languageserver-textdocument": "^1.0.11",
"vscode-ws-jsonrpc": "^3.1.0",
"minimatch": "^9.0.3",
"semver": "^7.5.4",
"@difizen/monaco-editor-core": "^0.39.4",
"vscode-uri": "^3.0.8",
"vscode-jsonrpc": "^8.2.0"
"vscode-uri": "^3.0.8"
},
"peerDependencies": {
"react": "^18.2.0"
},
"devDependencies": {
"@types/lodash.mergewith": "^4.6.9",
"@types/react": "^18.2.25",
"@types/uuid": "^9.0.2",
"@types/vscode": "^1.82.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,15 +523,15 @@ export class DidChangeTextDocumentFeature
}
}

public clear(): void {
public clear = (): void => {
this._pendingTextDocumentChanges.clear();
this._changeData.clear();
this._syncKind = TextDocumentSyncKind.None;
if (this._listener) {
this._listener.dispose();
this._listener = undefined;
}
}
};

public getPendingDocumentChanges(excludes: Set<string>): TextDocument[] {
if (this._pendingTextDocumentChanges.size === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ export class LibroFileWatcher implements FileSystemWatcher {
protected onDidDeleteEmitter = new EventEmitter<Uri>();
onDidDelete: Event<Uri> = this.onDidDeleteEmitter.event;
dispose() {
throw new Error('Method not implemented.');
// console.log('Method not implemented.');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,28 +148,25 @@ export class LibroWorkspace implements ILibroWorkspace {
};
};
onDidChangeTextDocument: Event<TextDocumentChangeEvent> = (listener, thisArgs) => {
return (
this.libroService.onNotebookCellChanged((e) => {
listener.call(thisArgs, {
document: l2c.asNotebookCell(e.cell).document,
contentChanges: e.changes.map((change) => {
return {
range: new Range(
change.range.start.line,
change.range.start.column,
change.range.end.line,
change.range.end.column,
),
rangeLength: change.rangeLength,
rangeOffset: change.rangeOffset,
text: change.text,
};
}),
reason: undefined,
});
}),
thisArgs
);
return this.libroService.onNotebookCellChanged((e) => {
return listener.call(thisArgs, {
document: l2c.asNotebookCell(e.cell).document,
contentChanges: e.changes.map((change) => {
return {
range: new Range(
change.range.start.line,
change.range.start.column,
change.range.end.line,
change.range.end.column,
),
rangeLength: change.rangeLength,
rangeOffset: change.rangeOffset,
text: change.text,
};
}),
reason: undefined,
});
});
};
onDidCreateFiles: Event<FileCreateEvent> = () => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,3 @@ export enum FileType {
}

export * from './extHostTypes.js';
export { CancellationToken } from 'vscode-jsonrpc';
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import { URL } from '@difizen/libro-common';
import { PageConfig } from '@difizen/libro-kernel';
import type { ILanguageServerManager } from '@difizen/libro-lsp';
import { ILanguageServerManagerFactory } from '@difizen/libro-lsp';
import { ApplicationContribution, inject, singleton } from '@difizen/mana-app';

import { CloseAction, ErrorAction } from './common/api.js';
Expand All @@ -13,34 +9,21 @@ import { LibroLanguageClientManager } from './libro-language-client-manager.js';
export class LibroLanguageClientContribution implements ApplicationContribution {
@inject(LibroLanguageClientManager)
protected readonly libroLanguageClientManager: LibroLanguageClientManager;
@inject(ILanguageServerManagerFactory)
protected readonly languageServerManagerFactory: ILanguageServerManagerFactory;

@inject(LSPEnv)
protected readonly lspEnv: LSPEnv;

protected languageServerManager?: ILanguageServerManager;

serverUri(languageServerId: string) {
const wsBase = PageConfig.getBaseUrl().replace(/^http/, 'ws');
return URL.join(wsBase, 'lsp', 'ws', languageServerId);
}

async onViewStart() {
// not block
this.startLanguageClients();
}

async startLanguageClients() {
await this.lspEnv.ready;
this.languageServerManager = this.languageServerManagerFactory({});
await this.languageServerManager.ready;
const serverIds = this.languageServerManager.getMatchingServers({
language: 'python',
});
const serverIds = await this.libroLanguageClientManager.getServers();

for (const serverId of serverIds) {
const serverUrl = this.serverUri(serverId);
await this.libroLanguageClientManager.getOrCreateLanguageClient(serverUrl, {
await this.libroLanguageClientManager.getOrCreateLanguageClient(serverId, {
name: `${serverId} Language Client`,
clientOptions: {
// use a language id as a document selector
Expand Down
103 changes: 93 additions & 10 deletions packages/libro-language-client/src/libro-language-client-manager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { singleton } from '@difizen/mana-app';
import { URL } from '@difizen/libro-common';
import { PageConfig } from '@difizen/libro-kernel';
import type { ILanguageServerManager, TSessionMap } from '@difizen/libro-lsp';
import { ILanguageServerManagerFactory } from '@difizen/libro-lsp';
import { singleton, inject, postConstruct, getOrigin } from '@difizen/mana-app';

import type { LibroLanguageClientOptions } from './libro-language-client.js';
import { LibroLanguageClient } from './libro-language-client.js';
Expand All @@ -8,21 +12,72 @@ interface IConnectionData {
languageClient: LibroLanguageClient;
}

export type LSPFeature = 'format';

@singleton()
export class LibroLanguageClientManager {
@inject(ILanguageServerManagerFactory)
protected readonly languageServerManagerFactory: ILanguageServerManagerFactory;

protected languageServerManager: ILanguageServerManager;

protected clientMap = new Map<string, IConnectionData>();

async getOrCreateLanguageClient(url: string, options: LibroLanguageClientOptions) {
if (this.clientMap.has(url)) {
return this.clientMap.get(url);
@postConstruct()
init() {
this.languageServerManager = this.languageServerManagerFactory({});
}

protected serverUri(languageServerId: string) {
const wsBase = PageConfig.getBaseUrl().replace(/^http/, 'ws');
return URL.join(wsBase, 'lsp', 'ws', languageServerId);
}

async getServers() {
await this.languageServerManager.ready;
const serverIds = this.languageServerManager.getMatchingServers({
language: 'python',
});
return serverIds;
}

async getServerSpecs() {
await this.languageServerManager.ready;
const specs = this.languageServerManager.getMatchingSpecs({
language: 'python',
});
return specs;
}

async refreshRunning() {
await this.languageServerManager.refreshRunning();
}

get sessionsChanged() {
return this.languageServerManager.sessionsChanged;
}

get sessions() {
const res: TSessionMap = new Map();
this.languageServerManager.sessions.forEach((item, key) => {
if (item.status === 'started') {
res.set(key, item);
}
});
return res;
}

async getOrCreateLanguageClient(
languageServerId: string,
options: LibroLanguageClientOptions,
) {
if (this.clientMap.has(languageServerId)) {
return this.clientMap.get(languageServerId);
}
const url = this.serverUri(languageServerId);
const client = await this.createLanguageClient(url, options);
this.clientMap.set(url, client);
// const featureState = client.languageClient
// .getFeature('textDocument/formatting')
// .getState();
// console.log(featureState);

this.clientMap.set(languageServerId, client);
this.refreshRunning();
return client;
}

Expand All @@ -32,4 +87,32 @@ export class LibroLanguageClientManager {
) => {
return LibroLanguageClient.createWebSocketLanguageClient(url, options);
};

async closeLanguageClient(languageServerId: string) {
await getOrigin(this.clientMap.get(languageServerId)?.languageClient)?.dispose();
getOrigin(this.clientMap.get(languageServerId)?.connection)?.close();
this.clientMap.delete(languageServerId);
this.refreshRunning();
}

async closeAllLanguageClient() {
const servers = await this.getServers();
await Promise.all(servers.map((server) => this.closeLanguageClient(server)));
this.refreshRunning();
}

getFeatureStatus(feature: LSPFeature): boolean {
let featureEnabled = false;
if (feature === 'format') {
this.clientMap.forEach((client) => {
const featureState = client.languageClient
.getFeature('textDocument/formatting')
.getState();
if (featureState.kind === 'document' && featureState.registrations === true) {
featureEnabled = true;
}
});
}
return featureEnabled;
}
}
1 change: 0 additions & 1 deletion packages/libro-language-client/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { LibroLanguageClientManager } from './libro-language-client-manager.js';

export const LibroLanguageClientModule = ManaModule.create()
.register(LibroLanguageClientManager, LibroLanguageClientContribution, LSPEnv)
// .register(LibroLanguageClientManager, LibroLanguageClientContribution, LSPEnv)
.register(MonacoLanguages, LibroWindow, LibroWorkspace)
.dependOn(LibroLSPModule)
.preload((ctx) => {
Expand Down
Loading

0 comments on commit 198707e

Please sign in to comment.