/
service-registry.ts
90 lines (80 loc) · 3.12 KB
/
service-registry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/******************************************************************************
* Copyright 2021 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import type { LangiumCoreServices } from './services.js';
import { UriUtils, type URI } from './utils/uri-util.js';
/**
* The core service registry provides access to the core language-specific services. These are resolved
* via the URI of a text document.
*/
export interface CoreServiceRegistryI {
/**
* Register a language via its injected services.
*/
register(language: LangiumCoreServices): void;
/**
* Retrieve the language-specific services for the given URI. In case only one language is
* registered, it may be used regardless of the URI format.
*/
getServices(uri: URI): LangiumCoreServices;
/**
* The full set of registered language services.
*/
readonly all: readonly LangiumCoreServices[];
}
/**
* Registry for Langium's core services
*/
export class CoreServiceRegistry implements CoreServiceRegistryI {
protected singleton?: LangiumCoreServices;
protected map?: Record<string, LangiumCoreServices>;
register(language: LangiumCoreServices): void {
if (!this.singleton && !this.map) {
// This is the first language to be registered; store it as singleton.
this.singleton = language;
return;
}
if (!this.map) {
this.map = {};
if (this.singleton) {
// Move the previous singleton instance to the new map.
for (const ext of this.singleton.LanguageMetaData.fileExtensions) {
this.map[ext] = this.singleton;
}
this.singleton = undefined;
}
}
// Store the language services in the map.
for (const ext of language.LanguageMetaData.fileExtensions) {
if (this.map[ext] !== undefined && this.map[ext] !== language) {
console.warn(`The file extension ${ext} is used by multiple languages. It is now assigned to '${language.LanguageMetaData.languageId}'.`);
}
this.map[ext] = language;
}
}
getServices(uri: URI): LangiumCoreServices {
if (this.singleton !== undefined) {
return this.singleton;
}
if (this.map === undefined) {
throw new Error('The service registry is empty. Use `register` to register the services of a language.');
}
const ext = UriUtils.extname(uri);
const services = this.map[ext];
if (!services) {
throw new Error(`The service registry contains no services for the extension '${ext}'.`);
}
return services;
}
get all(): readonly LangiumCoreServices[] {
if (this.singleton !== undefined) {
return [this.singleton];
}
if (this.map !== undefined) {
return Object.values(this.map);
}
return [];
}
}