Skip to content

Commit

Permalink
Make service containers readonly (#1635)
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew authored Aug 29, 2024
1 parent d5fcdd2 commit 5063a2b
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 94 deletions.
14 changes: 11 additions & 3 deletions packages/langium/src/dependency-injection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,20 @@ export function eagerLoad<T>(item: T): T {
function _inject<I, T>(module: Module<I, T>, injector?: any): T {
const proxy: any = new Proxy({} as any, {
deleteProperty: () => false,
get: (obj, prop) => _resolve(obj, prop, module, injector || proxy),
set: () => {
throw new Error('Cannot set property on injected service container');
},
get: (obj, prop) => {
if (prop === isProxy) {
return true;
} else {
return _resolve(obj, prop, module, injector || proxy);
}
},
getOwnPropertyDescriptor: (obj, prop) => (_resolve(obj, prop, module, injector || proxy), Object.getOwnPropertyDescriptor(obj, prop)), // used by for..in
has: (_, prop) => prop in module, // used by ..in..
ownKeys: () => [...Reflect.ownKeys(module), isProxy] // used by for..in
ownKeys: () => [...Object.getOwnPropertyNames(module)] // used by for..in
});
proxy[isProxy] = true;
return proxy;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/langium/src/lsp/default-lsp-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { DefaultWorkspaceSymbolProvider } from './workspace-symbol-provider.js';
* Context required for creating the default language-specific dependency injection module.
*/
export interface DefaultModuleContext extends DefaultCoreModuleContext {
shared: LangiumSharedServices;
readonly shared: LangiumSharedServices;
}

/**
Expand Down Expand Up @@ -66,7 +66,7 @@ export interface DefaultSharedModuleContext extends DefaultSharedCoreModuleConte
/**
* Represents an abstract language server connection
*/
connection?: Connection;
readonly connection?: Connection;
}

/**
Expand Down
66 changes: 33 additions & 33 deletions packages/langium/src/lsp/lsp-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,47 +49,47 @@ export type LangiumSharedServices = LangiumSharedCoreServices & LangiumSharedLSP
* LSP services for a specific language of which Langium provides default implementations.
*/
export type LangiumLSPServices = {
lsp: {
CompletionProvider?: CompletionProvider
DocumentHighlightProvider?: DocumentHighlightProvider
DocumentSymbolProvider?: DocumentSymbolProvider
HoverProvider?: HoverProvider
FoldingRangeProvider?: FoldingRangeProvider
DefinitionProvider?: DefinitionProvider
TypeProvider?: TypeDefinitionProvider
ImplementationProvider?: ImplementationProvider
ReferencesProvider?: ReferencesProvider
CodeActionProvider?: CodeActionProvider
SemanticTokenProvider?: SemanticTokenProvider
RenameProvider?: RenameProvider
Formatter?: Formatter
SignatureHelp?: SignatureHelpProvider
CallHierarchyProvider?: CallHierarchyProvider
TypeHierarchyProvider?: TypeHierarchyProvider
DeclarationProvider?: DeclarationProvider
InlayHintProvider?: InlayHintProvider
CodeLensProvider?: CodeLensProvider
DocumentLinkProvider?: DocumentLinkProvider
readonly lsp: {
readonly CompletionProvider?: CompletionProvider
readonly DocumentHighlightProvider?: DocumentHighlightProvider
readonly DocumentSymbolProvider?: DocumentSymbolProvider
readonly HoverProvider?: HoverProvider
readonly FoldingRangeProvider?: FoldingRangeProvider
readonly DefinitionProvider?: DefinitionProvider
readonly TypeProvider?: TypeDefinitionProvider
readonly ImplementationProvider?: ImplementationProvider
readonly ReferencesProvider?: ReferencesProvider
readonly CodeActionProvider?: CodeActionProvider
readonly SemanticTokenProvider?: SemanticTokenProvider
readonly RenameProvider?: RenameProvider
readonly Formatter?: Formatter
readonly SignatureHelp?: SignatureHelpProvider
readonly CallHierarchyProvider?: CallHierarchyProvider
readonly TypeHierarchyProvider?: TypeHierarchyProvider
readonly DeclarationProvider?: DeclarationProvider
readonly InlayHintProvider?: InlayHintProvider
readonly CodeLensProvider?: CodeLensProvider
readonly DocumentLinkProvider?: DocumentLinkProvider
},
shared: LangiumSharedServices
readonly shared: LangiumSharedServices
};

/**
* LSP services shared between multiple languages of which Langium provides default implementations.
*/
export type LangiumSharedLSPServices = {
lsp: {
Connection?: Connection
DocumentUpdateHandler: DocumentUpdateHandler
ExecuteCommandHandler?: ExecuteCommandHandler
FileOperationHandler?: FileOperationHandler
FuzzyMatcher: FuzzyMatcher
LanguageServer: LanguageServer
NodeKindProvider: NodeKindProvider
WorkspaceSymbolProvider?: WorkspaceSymbolProvider
readonly lsp: {
readonly Connection?: Connection
readonly DocumentUpdateHandler: DocumentUpdateHandler
readonly ExecuteCommandHandler?: ExecuteCommandHandler
readonly FileOperationHandler?: FileOperationHandler
readonly FuzzyMatcher: FuzzyMatcher
readonly LanguageServer: LanguageServer
readonly NodeKindProvider: NodeKindProvider
readonly WorkspaceSymbolProvider?: WorkspaceSymbolProvider
},
workspace: {
TextDocuments: TextDocuments<TextDocument>
readonly workspace: {
readonly TextDocuments: TextDocuments<TextDocument>
}
};

Expand Down
90 changes: 45 additions & 45 deletions packages/langium/src/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,52 +43,52 @@ import type { WorkspaceManager } from './workspace/workspace-manager.js';
* grammar definition and the language configuration.
*/
export type LangiumGeneratedCoreServices = {
Grammar: Grammar
LanguageMetaData: LanguageMetaData
parser: {
ParserConfig?: IParserConfig
readonly Grammar: Grammar
readonly LanguageMetaData: LanguageMetaData
readonly parser: {
readonly ParserConfig?: IParserConfig
}
}

/**
* Core services for a specific language of which Langium provides default implementations.
*/
export type LangiumDefaultCoreServices = {
parser: {
AsyncParser: AsyncParser
GrammarConfig: GrammarConfig
ValueConverter: ValueConverter
LangiumParser: LangiumParser
ParserErrorMessageProvider: IParserErrorMessageProvider
CompletionParser: LangiumCompletionParser
TokenBuilder: TokenBuilder
Lexer: Lexer
readonly parser: {
readonly AsyncParser: AsyncParser
readonly GrammarConfig: GrammarConfig
readonly ValueConverter: ValueConverter
readonly LangiumParser: LangiumParser
readonly ParserErrorMessageProvider: IParserErrorMessageProvider
readonly CompletionParser: LangiumCompletionParser
readonly TokenBuilder: TokenBuilder
readonly Lexer: Lexer
}
documentation: {
CommentProvider: CommentProvider
DocumentationProvider: DocumentationProvider
readonly documentation: {
readonly CommentProvider: CommentProvider
readonly DocumentationProvider: DocumentationProvider
}
references: {
Linker: Linker
NameProvider: NameProvider
References: References
ScopeProvider: ScopeProvider
ScopeComputation: ScopeComputation
readonly references: {
readonly Linker: Linker
readonly NameProvider: NameProvider
readonly References: References
readonly ScopeProvider: ScopeProvider
readonly ScopeComputation: ScopeComputation
}
serializer: {
Hydrator: Hydrator
JsonSerializer: JsonSerializer
readonly serializer: {
readonly Hydrator: Hydrator
readonly JsonSerializer: JsonSerializer
}
validation: {
DocumentValidator: DocumentValidator
ValidationRegistry: ValidationRegistry
readonly validation: {
readonly DocumentValidator: DocumentValidator
readonly ValidationRegistry: ValidationRegistry
}
workspace: {
AstNodeLocator: AstNodeLocator
AstNodeDescriptionProvider: AstNodeDescriptionProvider
ReferenceDescriptionProvider: ReferenceDescriptionProvider
readonly workspace: {
readonly AstNodeLocator: AstNodeLocator
readonly AstNodeDescriptionProvider: AstNodeDescriptionProvider
readonly ReferenceDescriptionProvider: ReferenceDescriptionProvider
}
shared: LangiumSharedCoreServices
readonly shared: LangiumSharedCoreServices
}

/**
Expand All @@ -102,24 +102,24 @@ export type LangiumCoreServices = LangiumGeneratedCoreServices & LangiumDefaultC
* derived from the grammar definition.
*/
export type LangiumGeneratedSharedCoreServices = {
AstReflection: AstReflection
readonly AstReflection: AstReflection
}

/**
* Core services shared between multiple languages where Langium provides default implementations.
*/
export type LangiumDefaultSharedCoreServices = {
ServiceRegistry: ServiceRegistry
workspace: {
ConfigurationProvider: ConfigurationProvider
DocumentBuilder: DocumentBuilder
FileSystemProvider: FileSystemProvider
IndexManager: IndexManager
LangiumDocuments: LangiumDocuments
LangiumDocumentFactory: LangiumDocumentFactory
TextDocuments?: TextDocumentProvider
WorkspaceLock: WorkspaceLock
WorkspaceManager: WorkspaceManager
readonly ServiceRegistry: ServiceRegistry
readonly workspace: {
readonly ConfigurationProvider: ConfigurationProvider
readonly DocumentBuilder: DocumentBuilder
readonly FileSystemProvider: FileSystemProvider
readonly IndexManager: IndexManager
readonly LangiumDocuments: LangiumDocuments
readonly LangiumDocumentFactory: LangiumDocumentFactory
readonly TextDocuments?: TextDocumentProvider
readonly WorkspaceLock: WorkspaceLock
readonly WorkspaceManager: WorkspaceManager
}
}

Expand Down
13 changes: 2 additions & 11 deletions packages/langium/test/dependency-injection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,18 +352,9 @@ describe('The inject result', () => {
expect('b' in obj).toBe(false);
});

test('should be extensible', () => {
test('should not be extensible', () => {
const obj: any = inject({});
expect(Object.isExtensible(obj)).toBe(true);
expect(obj.a).toBeUndefined();
expect(() => obj.a = 1).not.toThrow();
expect(obj.a).toBe(1);
});

test('should be sealable', () => {
const obj: any = Object.seal(inject({}));
expect(Object.isExtensible(obj)).toBe(false);
expect(() => (obj.a = 1)).toThrowError('Cannot define property a, object is not extensible');
expect(() => (obj.a = 1)).toThrowError('Cannot set property on injected service container');
});

});

0 comments on commit 5063a2b

Please sign in to comment.