Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escape ${ in template string #1514

Merged
merged 2 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/langium-cli/src/generator/grammar-serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ export function serializeGrammar(services: LangiumCoreServices, grammars: Gramma
});
// The json serializer returns strings with \n line delimiter by default
// We need to translate these line endings to the OS specific line ending
const json = normalizeEOL(serializedGrammar
let json = normalizeEOL(serializedGrammar
.replace(/\\/g, '\\\\')
.replace(new RegExp(delimiter, 'g'), '\\' + delimiter));
if (!production) {
Lotes marked this conversation as resolved.
Show resolved Hide resolved
// Escape ${ in template strings
json = json.replace(/\${/g, '\\${');
}
return expandToNode`

let loaded${grammar.name}Grammar: Grammar | undefined;
Expand Down
33 changes: 32 additions & 1 deletion packages/langium-cli/test/generator/grammar-serializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@

import type { LangiumConfig } from '../../src/package-types.js';
import { EmptyFileSystem, URI, type Grammar } from 'langium';
import { describe, expect, test } from 'vitest';
import { afterEach, describe, expect, test } from 'vitest';
import { RelativePath } from '../../src/package-types.js';
import { serializeGrammar } from '../../src/generator/grammar-serializer.js';
import { createLangiumGrammarServices } from 'langium/grammar';
import { expandToString } from 'langium/generate';
import { clearDocuments } from 'langium/test';

const grammarServices = createLangiumGrammarServices(EmptyFileSystem);

describe('Grammar serializer', () => {

afterEach(() => {
clearDocuments(grammarServices.shared);
});

test('should include comments of AST elements', async () => {
// arrange
const config: LangiumConfig = {
Expand Down Expand Up @@ -45,4 +51,29 @@ describe('Grammar serializer', () => {
expect(moduleString).toMatch('"$comment": "/**\\\\n * This is the entry rule\\\\n */"');
});

test('should escape template strings in development mode', async () => {
// arrange
const config: LangiumConfig = {
projectName: 'Magic',
languages: [],
Lotes marked this conversation as resolved.
Show resolved Hide resolved
[RelativePath]: '/path/to/magic',
};

const grammarText = expandToString`
grammar Test
entry Model: name='\${';
`;

const document = grammarServices.shared.workspace.LangiumDocumentFactory.fromString<Grammar>(grammarText, URI.file('test.langium'));
grammarServices.shared.workspace.LangiumDocuments.addDocument(document);
await grammarServices.shared.workspace.DocumentBuilder.build([document]);
const grammar = document.parseResult.value;

// act
const moduleString = serializeGrammar(grammarServices.grammar, [grammar], config);

// assert
expect(moduleString).toMatch('"value": "\\${"');
});

});
Loading