Skip to content

Commit

Permalink
Improve unknown file type handling in language server (#1455)
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Apr 22, 2024
1 parent 39e55c4 commit efbfab3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 17 deletions.
6 changes: 6 additions & 0 deletions packages/langium/src/lsp/document-update-handler.ts
Expand Up @@ -12,6 +12,7 @@ import type { TextDocument } from '../workspace/documents.js';
import type { WorkspaceLock } from '../workspace/workspace-lock.js';
import type { LangiumSharedServices } from './lsp-services.js';
import type { WorkspaceManager } from '../workspace/workspace-manager.js';
import type { ServiceRegistry } from '../service-registry.js';

/**
* Shared service for handling text document changes and watching relevant files.
Expand All @@ -35,11 +36,13 @@ export class DefaultDocumentUpdateHandler implements DocumentUpdateHandler {
protected readonly workspaceManager: WorkspaceManager;
protected readonly documentBuilder: DocumentBuilder;
protected readonly workspaceLock: WorkspaceLock;
protected readonly serviceRegistry: ServiceRegistry;

constructor(services: LangiumSharedServices) {
this.workspaceManager = services.workspace.WorkspaceManager;
this.documentBuilder = services.workspace.DocumentBuilder;
this.workspaceLock = services.workspace.WorkspaceLock;
this.serviceRegistry = services.ServiceRegistry;

let canRegisterFileWatcher = false;
services.lsp.LanguageServer.onInitialize(params => {
Expand Down Expand Up @@ -73,6 +76,9 @@ export class DefaultDocumentUpdateHandler implements DocumentUpdateHandler {
}

protected fireDocumentUpdate(changed: URI[], deleted: URI[]): void {
// Filter out URIs that do not have a service in the registry
// Running the document builder update will fail for those URIs
changed = changed.filter(uri => this.serviceRegistry.hasServices(uri));
// Only fire the document update when the workspace manager is ready
// Otherwise, we might miss the initial indexing of the workspace
this.workspaceManager.ready.then(() => {
Expand Down
2 changes: 2 additions & 0 deletions packages/langium/src/lsp/index.ts
Expand Up @@ -15,7 +15,9 @@ export * from './default-lsp-module.js';
export * from './document-highlight-provider.js';
export * from './document-link-provider.js';
export * from './document-symbol-provider.js';
export * from './document-update-handler.js';
export * from './execute-command-handler.js';
export * from './file-operation-handler.js';
export * from './folding-range-provider.js';
export * from './formatter.js';
export * from './fuzzy-matcher.js';
Expand Down
31 changes: 14 additions & 17 deletions packages/langium/src/lsp/language-server.ts
Expand Up @@ -640,12 +640,12 @@ export function createHierarchyRequestHandler<P extends TypeHierarchySupertypesP
if (cancellationError) {
return cancellationError;
}
const language = serviceRegistry.getServices(uri);
if (!language) {
const message = `Could not find service instance for uri: '${uri.toString()}'`;
console.error(message);
throw new Error(message);
if (!serviceRegistry.hasServices(uri)) {
const errorText = `Could not find service instance for uri: '${uri}'`;
console.debug(errorText);
return responseError<E>(new Error(errorText));
}
const language = serviceRegistry.getServices(uri);
try {
return await serviceCall(language, params, cancelToken);
} catch (err) {
Expand All @@ -667,14 +667,14 @@ export function createServerRequestHandler<P extends { textDocument: TextDocumen
if (cancellationError) {
return cancellationError;
}
const language = serviceRegistry.getServices(uri);
if (!language) {
if (!serviceRegistry.hasServices(uri)) {
const errorText = `Could not find service instance for uri: '${uri}'`;
console.error(errorText);
throw new Error(errorText);
console.debug(errorText);
return responseError<E>(new Error(errorText));
}
const document = await documents.getOrCreateDocument(uri);
const language = serviceRegistry.getServices(uri);
try {
const document = await documents.getOrCreateDocument(uri);
return await serviceCall(language, document, params, cancelToken);
} catch (err) {
return responseError<E>(err);
Expand All @@ -695,16 +695,13 @@ export function createRequestHandler<P extends { textDocument: TextDocumentIdent
if (cancellationError) {
return cancellationError;
}
const language = serviceRegistry.getServices(uri);
if (!language) {
console.error(`Could not find service instance for uri: '${uri.toString()}'`);
return null;
}
const document = documents.getDocument(uri);
if (!document) {
if (!serviceRegistry.hasServices(uri)) {
console.debug(`Could not find service instance for uri: '${uri.toString()}'`);
return null;
}
const language = serviceRegistry.getServices(uri);
try {
const document = await documents.getOrCreateDocument(uri);
return await serviceCall(language, document, params, cancelToken);
} catch (err) {
return responseError<E>(err);
Expand Down
14 changes: 14 additions & 0 deletions packages/langium/src/service-registry.ts
Expand Up @@ -24,6 +24,11 @@ export interface ServiceRegistry {
*/
getServices(uri: URI): LangiumCoreServices;

/**
* Check whether services are available for the given URI.
*/
hasServices(uri: URI): boolean;

/**
* The full set of registered language services.
*/
Expand Down Expand Up @@ -78,6 +83,15 @@ export class DefaultServiceRegistry implements ServiceRegistry {
return services;
}

hasServices(uri: URI): boolean {
try {
this.getServices(uri);
return true;
} catch {
return false;
}
}

get all(): readonly LangiumCoreServices[] {
if (this.singleton !== undefined) {
return [this.singleton];
Expand Down

0 comments on commit efbfab3

Please sign in to comment.