-
Notifications
You must be signed in to change notification settings - Fork 9
feat: VS Code web extension POC (vscode.dev support) #340
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { Languages } from '@blockception/ide-shared'; | ||
| import { LanguageClient, LanguageClientOptions } from 'vscode-languageclient/browser'; | ||
| import { Manager } from '../manager/manager'; | ||
| import * as vscode from 'vscode'; | ||
|
|
||
| export function setupClientBrowser(context: vscode.ExtensionContext): void { | ||
| console.log('starting minecraft language client (browser/web worker)'); | ||
|
|
||
| // Include vscode-vfs scheme used by vscode.dev / github.dev | ||
| const clientOptions: LanguageClientOptions = { | ||
| documentSelector: [ | ||
| { scheme: 'file', language: Languages.McFunctionIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.McFunctionIdentifier }, | ||
| { scheme: 'file', language: Languages.McLanguageIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.McLanguageIdentifier }, | ||
| { scheme: 'file', language: Languages.JsonIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.JsonIdentifier }, | ||
| { scheme: 'file', language: Languages.JsonCIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.JsonCIdentifier }, | ||
| { scheme: 'file', language: Languages.McProjectIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.McProjectIdentifier }, | ||
| { scheme: 'file', language: Languages.McMolangIdentifier }, | ||
| { scheme: 'vscode-vfs', language: Languages.McMolangIdentifier }, | ||
| ], | ||
| }; | ||
|
|
||
| // Use Uri.joinPath on context.extensionUri — NOT context.asAbsolutePath — | ||
| // because asAbsolutePath is not available in the browser extension host. | ||
| const serverUri = vscode.Uri.joinPath(context.extensionUri, 'lsp', 'server.browser.js'); | ||
| const worker = new Worker(serverUri.toString(/* skipEncoding= */ true)); | ||
|
|
||
| Manager.Client = new LanguageClient( | ||
| 'languageBlockceptionMinecraftClient', | ||
| 'LSP-BC Minecraft', | ||
| clientOptions, | ||
| worker, | ||
| ); | ||
|
|
||
| Manager.Client.start().then(() => { | ||
| vscode.commands.executeCommand('setContext', 'ext:is_active', true); | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| export * from './lsp/server/setup'; | ||
| export * from './lsp/server/setup.browser'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // Browser-specific server setup — uses vscode-languageserver/browser | ||
| // instead of vscode-languageserver/node. | ||
| import { BrowserMessageReader, BrowserMessageWriter, createConnection, ProposedFeatures } from 'vscode-languageserver/browser'; | ||
| import { LSPConfig } from '../config/config'; | ||
| import { setupServerCore } from './setup.core'; | ||
|
|
||
| export function setupServerBrowser(config: LSPConfig): void { | ||
| // self is the DedicatedWorkerGlobalScope inside the Web Worker | ||
| const messageReader = new BrowserMessageReader(self as DedicatedWorkerGlobalScope); | ||
| const messageWriter = new BrowserMessageWriter(self as DedicatedWorkerGlobalScope); | ||
| const connection = createConnection(ProposedFeatures.all, messageReader, messageWriter); | ||
| setupServerCore(connection, config); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| import { Connection, BulkRegistration, InitializeResult } from 'vscode-languageserver'; | ||
|
|
||
| import { CodeActionService } from '../code-action/service'; | ||
| import { CodeLensService } from '../code-lens/service'; | ||
| import { CommandService } from '../commands/service'; | ||
| import { DataSetService } from '../dataset/service'; | ||
| import { CompletionService } from '../completion/service'; | ||
| import { ConfigurationService } from '../configuration/service'; | ||
| import { Database } from '../database/database'; | ||
| import { DiagnoserService } from '../diagnostics/service'; | ||
| import { DocumentManager, IDocumentManager } from '../documents/manager'; | ||
| import { ExtensionContext } from '../extension'; | ||
| import { FormatService } from '../format/service'; | ||
| import { ExtendedLogger } from '../logger/logger'; | ||
| import { DocumentProcessor, PackProcessor, WorkspaceProcessor } from '../process'; | ||
| import { DefinitionService, ImplementationService, ReferenceService, TypeDefinitionService } from '../references'; | ||
| import { SemanticsServer } from '../semantics/service'; | ||
| import { CapabilityBuilder } from '../services/capabilities'; | ||
| import { ServiceManager } from '../services/collection'; | ||
| import { SignatureService } from '../signatures/service'; | ||
| import { DocumentSymbolService } from '../symbols/document-service'; | ||
| import { WorkspaceSymbolService } from '../symbols/workspace-service'; | ||
| import { LSPConfig } from '../config/config'; | ||
|
|
||
| export function setupServerCore(connection: Connection, config: LSPConfig): void { | ||
| const logger = new ExtendedLogger(connection.console); | ||
| const manager = new ServiceManager(logger); | ||
| const extension = new ExtensionContext(config, connection, manager, logger, {} as IDocumentManager, {} as Database); | ||
| const documents = new DocumentManager(logger, extension); | ||
| const database = new Database(logger, documents); | ||
| extension.documents = documents; | ||
| extension.database = database; | ||
|
|
||
| const diagnoserService = new DiagnoserService(logger, extension, documents); | ||
| const documentProcessor = new DocumentProcessor(logger, extension, diagnoserService); | ||
| const packProcessor = new PackProcessor(logger, extension, documentProcessor); | ||
| const workspaceProcessor = new WorkspaceProcessor(logger, extension, packProcessor); | ||
|
|
||
| manager | ||
| // Essentials | ||
| .add(new ConfigurationService(logger, extension), documents, database) | ||
| // Non Essentials | ||
| .add( | ||
| diagnoserService, | ||
| documentProcessor, | ||
| packProcessor, | ||
| workspaceProcessor, | ||
| new CodeActionService(logger, extension), | ||
| new CodeLensService(logger, extension), | ||
| new CommandService(logger, extension), | ||
| new DataSetService(logger, extension), | ||
| new CompletionService(logger, extension), | ||
| new DefinitionService(logger, extension), | ||
| new DocumentSymbolService(logger, extension), | ||
| new FormatService(logger, extension), | ||
| new ImplementationService(logger, extension), | ||
| new ReferenceService(logger, extension), | ||
| new SemanticsServer(logger, extension), | ||
| new SignatureService(logger, extension), | ||
| new TypeDefinitionService(logger, extension), | ||
| new WorkspaceSymbolService(logger, extension), | ||
| ); | ||
|
|
||
| logger.info('starting minecraft server'); | ||
|
|
||
| //Initialize | ||
| connection.onInitialize((params, token, workDoneProgress) => { | ||
| workDoneProgress.begin('initializing', 0); | ||
|
|
||
| logger.info('Initializing minecraft server', { version: config.version }); | ||
| const result: InitializeResult = { | ||
| serverInfo: { | ||
| name: 'bc-minecraft-language-server', | ||
| version: config.version, | ||
| }, | ||
| capabilities: {}, | ||
| }; | ||
| const builder = new CapabilityBuilder(result.capabilities); | ||
|
|
||
| extension.parseClientCapabilities(params.capabilities); | ||
| manager.onInitialize(builder, params, token, workDoneProgress); | ||
|
|
||
| result.capabilities = builder.result(); | ||
|
|
||
| workDoneProgress.done(); | ||
| return result; | ||
| }); | ||
|
|
||
| // This handler provides diagnostics | ||
| connection.onInitialized(async () => { | ||
| logger.info('Initialized minecraft server', { version: config.version }); | ||
| manager.setupHandlers(connection); | ||
|
|
||
| //Registers any follow ups | ||
| const register = BulkRegistration.create(); | ||
| manager.dynamicRegister(register); | ||
| await connection.client.register(register); | ||
|
|
||
| return manager.start(); | ||
| }); | ||
|
|
||
| // On shutdown handler | ||
| connection.onShutdown(() => { | ||
| logger.info('Shutting down server'); | ||
| manager.stop(); | ||
| }); | ||
|
|
||
| connection.onExit(() => { | ||
| logger.info('exiting server'); | ||
| manager.dispose(); | ||
| }); | ||
|
|
||
| // Listen on the connection | ||
| connection.listen(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,118 +1,10 @@ | ||
| import { BulkRegistration, createConnection, InitializeResult, ProposedFeatures } from 'vscode-languageserver/node'; | ||
| import { CodeActionService } from '../code-action/service'; | ||
| import { CodeLensService } from '../code-lens/service'; | ||
| import { CommandService } from '../commands/service'; | ||
| import { DataSetService } from '../dataset/service'; | ||
| import { CompletionService } from '../completion/service'; | ||
| import { ConfigurationService } from '../configuration/service'; | ||
| import { Database } from '../database/database'; | ||
| import { DiagnoserService } from '../diagnostics/service'; | ||
| import { DocumentManager, IDocumentManager } from '../documents/manager'; | ||
| import { ExtensionContext } from '../extension'; | ||
| import { FormatService } from '../format/service'; | ||
| import { ExtendedLogger } from '../logger/logger'; | ||
| import { DocumentProcessor, PackProcessor, WorkspaceProcessor } from '../process'; | ||
| import { DefinitionService, ImplementationService, ReferenceService, TypeDefinitionService } from '../references'; | ||
| import { SemanticsServer } from '../semantics/service'; | ||
| import { CapabilityBuilder } from '../services/capabilities'; | ||
| import { ServiceManager } from '../services/collection'; | ||
| import { SignatureService } from '../signatures/service'; | ||
| import { DocumentSymbolService } from '../symbols/document-service'; | ||
| import { WorkspaceSymbolService } from '../symbols/workspace-service'; | ||
| import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'; | ||
| import { LSPConfig } from '../config/config'; | ||
| import { setupServerCore } from './setup.core'; | ||
|
|
||
| export function setupServer(config: LSPConfig) { | ||
| export function setupServer(config: LSPConfig): void { | ||
| // Create a connection for the server, using Node's IPC as a transport. | ||
| // Also include all preview / proposed LSP features. | ||
| const connection = createConnection(ProposedFeatures.all); | ||
|
|
||
| const logger = new ExtendedLogger(connection.console); | ||
| const manager = new ServiceManager(logger); | ||
| const extension = new ExtensionContext(config, connection, manager, logger, {} as IDocumentManager, {} as Database); | ||
| const documents = new DocumentManager(logger, extension); | ||
| const database = new Database(logger, documents); | ||
| extension.documents = documents; | ||
| extension.database = database; | ||
|
|
||
| const diagnoserService = new DiagnoserService(logger, extension, documents); | ||
| const documentProcessor = new DocumentProcessor(logger, extension, diagnoserService); | ||
| const packProcessor = new PackProcessor(logger, extension, documentProcessor); | ||
| const workspaceProcessor = new WorkspaceProcessor(logger, extension, packProcessor); | ||
|
|
||
| manager | ||
| // Essentials | ||
| .add(new ConfigurationService(logger, extension), documents, database) | ||
| // Non Essentials | ||
| .add( | ||
| diagnoserService, | ||
| documentProcessor, | ||
| packProcessor, | ||
| workspaceProcessor, | ||
| new CodeActionService(logger, extension), | ||
| new CodeLensService(logger, extension), | ||
| new CommandService(logger, extension), | ||
| new DataSetService(logger, extension), | ||
| new CompletionService(logger, extension), | ||
| new DefinitionService(logger, extension), | ||
| new DocumentSymbolService(logger, extension), | ||
| new FormatService(logger, extension), | ||
| new ImplementationService(logger, extension), | ||
| new ReferenceService(logger, extension), | ||
| new SemanticsServer(logger, extension), | ||
| new SignatureService(logger, extension), | ||
| new TypeDefinitionService(logger, extension), | ||
| new WorkspaceSymbolService(logger, extension), | ||
| ); | ||
|
|
||
| logger.info('starting minecraft server'); | ||
|
|
||
| //Initialize | ||
| connection.onInitialize((params, token, workDoneProgress) => { | ||
| workDoneProgress.begin('initializing', 0); | ||
|
|
||
| logger.info('Initializing minecraft server', { version: config.version }); | ||
| const result: InitializeResult = { | ||
| serverInfo: { | ||
| name: 'bc-minecraft-language-server', | ||
| version: config.version, | ||
| }, | ||
| capabilities: {}, | ||
| }; | ||
| const builder = new CapabilityBuilder(result.capabilities); | ||
|
|
||
| extension.parseClientCapabilities(params.capabilities); | ||
| manager.onInitialize(builder, params, token, workDoneProgress); | ||
|
|
||
| result.capabilities = builder.result(); | ||
|
|
||
| workDoneProgress.done(); | ||
| return result; | ||
| }); | ||
|
|
||
| // This handler provides diagnostics | ||
| connection.onInitialized(async () => { | ||
| logger.info('Initialized minecraft server', { version: config.version }); | ||
| manager.setupHandlers(connection); | ||
|
|
||
| //Registers any follow ups | ||
| const register = BulkRegistration.create(); | ||
| manager.dynamicRegister(register); | ||
| await connection.client.register(register); | ||
|
|
||
| return manager.start(); | ||
| }); | ||
|
|
||
| // On shutdown handler | ||
| connection.onShutdown(() => { | ||
| logger.info('Shutting down server'); | ||
| manager.stop(); | ||
| }); | ||
|
|
||
| connection.onExit(() => { | ||
| logger.info('exiting server'); | ||
| manager.dispose(); | ||
| }); | ||
|
|
||
| // Listen on the connection | ||
| connection.listen(); | ||
| setupServerCore(connection, config); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import * as vscode from 'vscode'; | ||
| import { setupClientBrowser, Manager } from 'bc-minecraft-lsp-client'; | ||
|
|
||
| export function activate(context: vscode.ExtensionContext): void { | ||
| setupClientBrowser(context); | ||
| } | ||
|
|
||
| export function deactivate(): Thenable<void> | undefined { | ||
| console.log('stopping minecraft language client (browser)'); | ||
| if (!Manager.Client) { | ||
| return undefined; | ||
| } | ||
| return Manager.Client.stop(); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,4 @@ | ||||||
| import { setupServerBrowser } from 'bc-minecraft-lsp'; | ||||||
|
||||||
| import { setupServerBrowser } from 'bc-minecraft-lsp'; | |
| import { setupServerBrowser } from 'bc-minecraft-lsp/browser'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Importing
setupServerBrowserfrombc-minecraft-lspgoes throughide/base/server/src/index.ts, which now re-exports the NodesetupServermodule as well. That causes the browser server bundle to pull invscode-languageserver/node(and other Node-only dependencies) even though only the browser setup is needed. Expose a separate browser-only entry/module (or conditional exports) so the web worker bundle never imports the Node setup path.