UNPKG

langium-cli

Version:

CLI for Langium - the language engineering tool

126 lines (110 loc) 6.36 kB
/****************************************************************************** * 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 { Grammar, IParserConfig } from 'langium'; import { type Generated, expandToNode, joinToNode, toString } from 'langium/generate'; import type { LangiumConfig, LangiumLanguageConfig } from '../package-types.js'; import { generatedHeader } from './node-util.js'; export function generateModule(grammars: Grammar[], config: LangiumConfig, grammarConfigMap: Map<Grammar, LangiumLanguageConfig>): string { const grammarsWithName = grammars.filter(grammar => !!grammar.name); const parserConfig = config.chevrotainParserConfig; const mode = config.mode; const hasIParserConfigImport = Boolean(parserConfig) || grammars.some(grammar => grammarConfigMap.get(grammar)?.chevrotainParserConfig !== undefined); let needsGeneralParserConfig = undefined; /* eslint-disable @stylistic/indent */ const node = expandToNode` ${generatedHeader} `.appendNewLine( ).appendIf(!!config.langiumInternal, expandToNode` import type { LanguageMetaData } from '../../languages/language-meta-data${config.importExtension}'; import { ${config.projectName}AstReflection } from '../../languages/generated/ast${config.importExtension}'; import type { Module } from '../../dependency-injection${config.importExtension}'; import type { LangiumSharedCoreServices, LangiumCoreServices, LangiumGeneratedCoreServices, LangiumGeneratedSharedCoreServices } from '../../services${config.importExtension}'; `.appendTemplateIf(hasIParserConfigImport)` import type { IParserConfig } from '../../parser/parser-config${config.importExtension}'; ` ).appendTemplateIf(!config.langiumInternal)` import type { LangiumSharedCoreServices, LangiumCoreServices, LangiumGeneratedCoreServices, LangiumGeneratedSharedCoreServices, LanguageMetaData, Module${hasIParserConfigImport ? ', IParserConfig' : ''} } from 'langium'; import { ${config.projectName}AstReflection } from './ast${config.importExtension}'; `.appendTemplate` import { ${joinToNode(grammarsWithName, grammar => grammar.name + 'Grammar', { separator: ', '}) } } from './grammar${config.importExtension}'; ${joinToNode( grammarsWithName, grammar => { const config = grammarConfigMap.get(grammar)!; const modeValue = mode === 'production' ? mode : 'development'; return expandToNode` export const ${ grammar.name }LanguageMetaData = { languageId: '${config.id}', fileExtensions: [${config.fileExtensions && joinToNode(config.fileExtensions, e => appendQuotesAndDot(e), { separator: ', ' })}], ${config.fileNames ? `fileNames: [${config.fileNames.map(name => `'${name}'`).join(', ')}],` : undefined} caseInsensitive: ${Boolean(config.caseInsensitive)}, mode: '${modeValue}' } as const satisfies LanguageMetaData; `; }, { appendNewLineIfNotEmpty: true } )} ${joinToNode( grammarsWithName, grammar => { const grammarParserConfig = grammarConfigMap.get(grammar)!.chevrotainParserConfig; if (grammarParserConfig) { return expandToNode` export const ${grammar.name}ParserConfig: IParserConfig = { ${generateParserConfig(grammarParserConfig)} }; `; } else { needsGeneralParserConfig = true; return; } }, { appendNewLineIfNotEmpty: true } )} ${needsGeneralParserConfig && parserConfig && expandToNode` export const parserConfig: IParserConfig = { ${generateParserConfig(parserConfig)} }; `} export const ${config.projectName}GeneratedSharedModule: Module<LangiumSharedCoreServices, LangiumGeneratedSharedCoreServices> = { AstReflection: () => new ${config.projectName}AstReflection() }; ${joinToNode( grammarsWithName, grammar => { const grammarConfig = grammarConfigMap.get(grammar)!; return expandToNode` export const ${grammar.name}GeneratedModule: Module<LangiumCoreServices, LangiumGeneratedCoreServices> = { Grammar: () => ${grammar.name}Grammar(), LanguageMetaData: () => ${grammar.name}LanguageMetaData, parser: {${(grammarConfig.chevrotainParserConfig || parserConfig) && expandToNode` ${'' /** needed to add the linebreak after the opening brace in case content is to be added, and to enable 'expandToNode' to identify the correct intendation of the subseqent parts. */} ${grammarConfig.chevrotainParserConfig ? `ParserConfig: () => ${grammar.name}ParserConfig` : undefined} ${!grammarConfig.chevrotainParserConfig && parserConfig ? 'ParserConfig: () => parserConfig' : undefined} `}} }; `; }, { appendNewLineIfNotEmpty: true} )} `; /* eslint-enable @stylistic/indent */ return toString(node); } function generateParserConfig(config: IParserConfig): Generated { return joinToNode( Object.entries(config), ([key, value]) => `${key}: ${typeof value === 'string' ? `'${value}'` : value},`, { appendNewLineIfNotEmpty: true } ); } function appendQuotesAndDot(input: string): string { if (!input.startsWith('.')) { input = '.' + input; } return `'${input}'`; }