44 * terms of the MIT License, which is available in the project root.
55 ******************************************************************************/
66
7- import type { LangiumCoreServices } from './services.js' ;
7+ import type { LangiumCoreServices , LangiumSharedCoreServices } from './services.js' ;
8+ import type { TextDocumentProvider } from './workspace/documents.js' ;
89import { UriUtils , type URI } from './utils/uri-utils.js' ;
910
1011/**
@@ -41,44 +42,60 @@ export interface ServiceRegistry {
4142export class DefaultServiceRegistry implements ServiceRegistry {
4243
4344 protected singleton ?: LangiumCoreServices ;
44- protected map ?: Record < string , LangiumCoreServices > ;
45+ protected readonly languageIdMap = new Map < string , LangiumCoreServices > ( ) ;
46+ protected readonly fileExtensionMap = new Map < string , LangiumCoreServices > ( ) ;
47+
48+ /**
49+ * @deprecated Use the new `fileExtensionMap` (or `languageIdMap`) property instead.
50+ */
51+ protected get map ( ) : Map < string , LangiumCoreServices > | undefined {
52+ return this . fileExtensionMap ;
53+ }
54+
55+ protected readonly textDocuments ?: TextDocumentProvider ;
56+
57+ constructor ( services ?: LangiumSharedCoreServices ) {
58+ this . textDocuments = services ?. workspace . TextDocuments ;
59+ }
4560
4661 register ( language : LangiumCoreServices ) : void {
47- if ( ! this . singleton && ! this . map ) {
48- // This is the first language to be registered; store it as singleton.
49- this . singleton = language ;
50- return ;
51- }
52- if ( ! this . map ) {
53- this . map = { } ;
54- if ( this . singleton ) {
55- // Move the previous singleton instance to the new map.
56- for ( const ext of this . singleton . LanguageMetaData . fileExtensions ) {
57- this . map [ ext ] = this . singleton ;
58- }
59- this . singleton = undefined ;
62+ const data = language . LanguageMetaData ;
63+ for ( const ext of data . fileExtensions ) {
64+ if ( this . fileExtensionMap . has ( ext ) ) {
65+ console . warn ( `The file extension ${ ext } is used by multiple languages. It is now assigned to '${ data . languageId } '.` ) ;
6066 }
67+ this . fileExtensionMap . set ( ext , language ) ;
6168 }
62- // Store the language services in the map.
63- for ( const ext of language . LanguageMetaData . fileExtensions ) {
64- if ( this . map [ ext ] !== undefined && this . map [ ext ] !== language ) {
65- console . warn ( `The file extension ${ ext } is used by multiple languages. It is now assigned to '${ language . LanguageMetaData . languageId } '.` ) ;
66- }
67- this . map [ ext ] = language ;
69+ this . languageIdMap . set ( data . languageId , language ) ;
70+ if ( this . languageIdMap . size === 1 ) {
71+ this . singleton = language ;
72+ } else {
73+ this . singleton = undefined ;
6874 }
6975 }
7076
7177 getServices ( uri : URI ) : LangiumCoreServices {
7278 if ( this . singleton !== undefined ) {
7379 return this . singleton ;
7480 }
75- if ( this . map === undefined ) {
81+ if ( this . languageIdMap . size === 0 ) {
7682 throw new Error ( 'The service registry is empty. Use `register` to register the services of a language.' ) ;
7783 }
84+ const languageId = this . textDocuments ?. get ( uri . toString ( ) ) ?. languageId ;
85+ if ( languageId !== undefined ) {
86+ const services = this . languageIdMap . get ( languageId ) ;
87+ if ( services ) {
88+ return services ;
89+ }
90+ }
7891 const ext = UriUtils . extname ( uri ) ;
79- const services = this . map [ ext ] ;
92+ const services = this . fileExtensionMap . get ( ext ) ;
8093 if ( ! services ) {
81- throw new Error ( `The service registry contains no services for the extension '${ ext } '.` ) ;
94+ if ( languageId ) {
95+ throw new Error ( `The service registry contains no services for the extension '${ ext } ' for language '${ languageId } '.` ) ;
96+ } else {
97+ throw new Error ( `The service registry contains no services for the extension '${ ext } '.` ) ;
98+ }
8299 }
83100 return services ;
84101 }
@@ -93,12 +110,6 @@ export class DefaultServiceRegistry implements ServiceRegistry {
93110 }
94111
95112 get all ( ) : readonly LangiumCoreServices [ ] {
96- if ( this . singleton !== undefined ) {
97- return [ this . singleton ] ;
98- }
99- if ( this . map !== undefined ) {
100- return Object . values ( this . map ) ;
101- }
102- return [ ] ;
113+ return Array . from ( this . languageIdMap . values ( ) ) ;
103114 }
104115}
0 commit comments