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

Partly revert change "Fix generator support on Windows (#857)"; introduced 'expandToStringLF' and 'expandToStringLFWithNL' #1274

Merged
merged 1 commit into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 5 additions & 5 deletions examples/statemachine/test/generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import type { Generated } from 'langium';
import type { Statemachine } from '../src/language-server/generated/ast.js';
import { describe, expect, test } from 'vitest';
import { EmptyFileSystem, normalizeEOL, toString } from 'langium';
import { EmptyFileSystem, expandToStringWithNL, toString } from 'langium';
import { parseHelper } from 'langium/test';
import { generateCppContent } from '../src/cli/generator.js';
import { createStatemachineServices } from '../src/language-server/statemachine-module.js';
Expand All @@ -31,7 +31,7 @@ describe('Tests the code generator', () => {
});
});

const input = `
const input = expandToStringWithNL`
statemachine TrafficLight

events
Expand Down Expand Up @@ -60,8 +60,8 @@ const input = `
end
`;

const expectedOutput =
normalizeEOL(`#include <iostream>
const expectedOutput = expandToStringWithNL`
#include <iostream>
#include <map>
#include <string>

Expand Down Expand Up @@ -213,4 +213,4 @@ int main() {
delete statemachine;
return 0;
}
`);
`;
127 changes: 63 additions & 64 deletions packages/langium-cli/test/generator/types-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import type { Grammar } from 'langium';
import { describe, expect, test } from 'vitest';
import { createLangiumGrammarServices, EmptyFileSystem, normalizeEOL } from 'langium';
import { createLangiumGrammarServices, EmptyFileSystem, expandToStringWithNL } from 'langium';
import { parseHelper } from 'langium/test';
import { generateTypesFile } from '../../src/generator/types-generator.js';

Expand All @@ -24,90 +24,89 @@ describe('Types generator', () => {

});

const EXPECTED_TYPES =
normalizeEOL(`type AbstractDefinition = DeclaredParameter | Definition;
const EXPECTED_TYPES = expandToStringWithNL`
type AbstractDefinition = DeclaredParameter | Definition;

type Expression = BinaryExpression | FunctionCall | NumberLiteral;
type Expression = BinaryExpression | FunctionCall | NumberLiteral;

type Statement = Definition | Evaluation;
type Statement = Definition | Evaluation;

interface BinaryExpression {
left: Expression
operator: "*" | "+" | "-" | "/"
right: Expression
}
interface BinaryExpression {
left: Expression
operator: "*" | "+" | "-" | "/"
right: Expression
}

interface DeclaredParameter {
name: string
}
interface DeclaredParameter {
name: string
}

interface Definition {
args: DeclaredParameter[]
expr: Expression
name: string
}
interface Definition {
args: DeclaredParameter[]
expr: Expression
name: string
}

interface Evaluation {
expression: Expression
}
interface Evaluation {
expression: Expression
}

interface FunctionCall {
args: Expression[]
func: @AbstractDefinition
}
interface FunctionCall {
args: Expression[]
func: @AbstractDefinition
}

interface Module {
name: string
statements: Statement[]
}
interface Module {
name: string
statements: Statement[]
}

interface NumberLiteral {
value: number
}
interface NumberLiteral {
value: number
}

`);
`;

const TEST_GRAMMAR =
`
grammar Arithmetics
const TEST_GRAMMAR = expandToStringWithNL`
grammar Arithmetics

entry Module:
'module' name=ID
(statements+=Statement)*;
entry Module:
'module' name=ID
(statements+=Statement)*;

Statement:
Definition | Evaluation;
Statement:
Definition | Evaluation;

Definition:
'def' name=ID ('(' args+=DeclaredParameter (',' args+=DeclaredParameter)* ')')?
':' expr=Expression ';';
Definition:
'def' name=ID ('(' args+=DeclaredParameter (',' args+=DeclaredParameter)* ')')?
':' expr=Expression ';';

DeclaredParameter:
name=ID;
DeclaredParameter:
name=ID;

type AbstractDefinition = Definition | DeclaredParameter;
type AbstractDefinition = Definition | DeclaredParameter;

Evaluation:
expression=Expression ';';
Evaluation:
expression=Expression ';';

Expression:
Addition;
Expression:
Addition;

Addition infers Expression:
Multiplication ({infer BinaryExpression.left=current} operator=('+' | '-') right=Multiplication)*;
Addition infers Expression:
Multiplication ({infer BinaryExpression.left=current} operator=('+' | '-') right=Multiplication)*;

Multiplication infers Expression:
PrimaryExpression ({infer BinaryExpression.left=current} operator=('*' | '/') right=PrimaryExpression)*;
Multiplication infers Expression:
PrimaryExpression ({infer BinaryExpression.left=current} operator=('*' | '/') right=PrimaryExpression)*;

PrimaryExpression infers Expression:
'(' Expression ')' |
{infer NumberLiteral} value=NUMBER |
{infer FunctionCall} func=[AbstractDefinition] ('(' args+=Expression (',' args+=Expression)* ')')?;
PrimaryExpression infers Expression:
'(' Expression ')' |
{infer NumberLiteral} value=NUMBER |
{infer FunctionCall} func=[AbstractDefinition] ('(' args+=Expression (',' args+=Expression)* ')')?;

hidden terminal WS: /\\s+/;
terminal ID: /[_a-zA-Z][\\w_]*/;
terminal NUMBER returns number: /[0-9]+(\\.[0-9]*)?/;
hidden terminal WS: /\\s+/;
terminal ID: /[_a-zA-Z][\\w_]*/;
terminal NUMBER returns number: /[0-9]+(\\.[0-9]*)?/;

hidden terminal ML_COMMENT: /\\/\\*[\\s\\S]*?\\*\\//;
hidden terminal SL_COMMENT: /\\/\\/[^\\n\\r]*/;
hidden terminal ML_COMMENT: /\\/\\*[\\s\\S]*?\\*\\//;
hidden terminal SL_COMMENT: /\\/\\/[^\\n\\r]*/;
`;
3 changes: 2 additions & 1 deletion packages/langium/src/generator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export * from './generator-node.js';
export type { SourceRegion, TextRegion, TraceRegion, TraceSourceSpec } from './generator-tracing.js';
export * from './node-joiner.js';
export * from './template-node.js';
export { expandToString, expandToStringWithNL, normalizeEOL } from './template-string.js';
export { expandToString, expandToStringLF, expandToStringLFWithNL, expandToStringWithNL, normalizeEOL } from './template-string.js';

27 changes: 24 additions & 3 deletions packages/langium/src/generator/template-string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,35 @@ export function expandToStringWithNL(staticParts: TemplateStringsArray, ...subst
return expandToString(staticParts, ...substitutions) + EOL;
}

export function expandToStringLFWithNL(staticParts: TemplateStringsArray, ...substitutions: unknown[]): string {
return expandToStringLF(staticParts, ...substitutions) + '\n';
}

/**
* A tag function that automatically aligns embedded multiline strings.
* Multiple lines are joined with the platform-specific line separator.
*
* @param staticParts the static parts of a tagged template literal
* @param substitutions the variable parts of a tagged template literal
* @returns an aligned string that consists of the given parts
*/
export function expandToString(staticParts: TemplateStringsArray, ...substitutions: unknown[]): string {
return internalExpandToString(EOL, staticParts, ...substitutions);
}

/**
* A tag function that automatically aligns embedded multiline strings.
* Multiple lines are joined with the LINE_FEED (`\n`) line separator.
*
* @param staticParts the static parts of a tagged template literal
* @param substitutions the variable parts of a tagged template literal
* @returns an aligned string that consists of the given parts
*/
export function expandToStringLF(staticParts: TemplateStringsArray, ...substitutions: unknown[]): string {
return internalExpandToString('\n', staticParts, ...substitutions);
}

function internalExpandToString(lineSep: string, staticParts: TemplateStringsArray, ...substitutions: unknown[]): string {
let lines = substitutions
// align substitutions and fuse them with static parts
.reduce((acc: string, subst: unknown, i: number) => acc + (subst === undefined ? SNLE : align(toString(subst), acc)) + (staticParts[i + 1] ?? ''), staticParts[0])
Expand Down Expand Up @@ -51,9 +72,9 @@ export function expandToString(staticParts: TemplateStringsArray, ...substitutio
const indent = findIndentation(lines);
return lines
// shifts lines to the left
.map(line => line.slice(indent).trimRight())
.map(line => line.slice(indent).trimEnd())
// convert lines to string
.join(EOL);
.join(lineSep);
}

export const SNLE = Object.freeze('__«SKIP^NEW^LINE^IF^EMPTY»__');
Expand All @@ -76,4 +97,4 @@ export function findIndentation(lines: string[]): number {

export function normalizeEOL(input: string): string {
return input.replace(NEWLINE_REGEXP, EOL);
}
}
20 changes: 10 additions & 10 deletions packages/langium/test/generator/template-string.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
******************************************************************************/

import { expect, test } from 'vitest';
import { expandToString as s, normalizeEOL } from 'langium';
import { expandToStringLF as s } from 'langium';

test('Should not throw when substituting null', () => {
expect(s`${null}`).toBe('null');
Expand All @@ -16,10 +16,10 @@ test('Should not throw when substituting undefined', () => {
});

test('Should omit lines containing just a subsitution being undefined', () => {
const expected = normalizeEOL(`123
const expected = `123
456
abc
def`);
def`;
expect(s`
123
${456}
Expand Down Expand Up @@ -70,8 +70,8 @@ const frayedIndentation = s`
test2
`;

const expectedFrayedIndentation = normalizeEOL(` test1
test2`);
const expectedFrayedIndentation = ` test1
test2`;

const trimmedMultilineString = s`
${1}
Expand All @@ -86,7 +86,7 @@ const multilineStringWithWhitespace = s`
${3}${''}
`;

const expectedMultilineStringWithWhitespace = normalizeEOL('// we add some right space\n1\n 2\n 3');
const expectedMultilineStringWithWhitespace = '// we add some right space\n1\n 2\n 3';

const generator = () => {
const applyMethod = (paramName: string) => s`
Expand All @@ -105,12 +105,12 @@ const generator = () => {
`;
};

const expectedGeneratorOutput = normalizeEOL(`public interface PartialFunction<T, R> {
const expectedGeneratorOutput = `public interface PartialFunction<T, R> {
R apply(T t);
boolean isDefinedAt(T t);
@Override
String toString() { return "T -> R"; }
}`);
}`;

const nestedIndentation = s`
${1}x
Expand All @@ -120,6 +120,6 @@ ${1}x
`}
`;

const expectedNestedIndentation = normalizeEOL(`1x
const expectedNestedIndentation = `1x
test1
test2`);
test2`;