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

feat: syntax and formatting for literal types #529

Merged
merged 10 commits into from
Jul 11, 2023
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ coverage/
dist/
dist-ssr/
out/
DSL/syntaxes/safe-ds.tmLanguage.json

# Node
.npm/
Expand Down
31 changes: 28 additions & 3 deletions DSL/src/language-server/formatting/safe-ds-formatter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AbstractFormatter, AstNode, CstNode, findCommentNode, Formatting, isAstNode } from 'langium';
import * as ast from '../generated/ast';
import { SdsImport, SdsImportAlias, SdsModule } from '../generated/ast';
import { annotationCallsOrEmpty, typeArgumentsOrEmpty } from '../helpers/astShortcuts';
import { annotationCallsOrEmpty, literalsOrEmpty, typeArgumentsOrEmpty } from '../helpers/astShortcuts';
import { FormattingAction, FormattingActionOptions } from 'langium/src/lsp/formatter';
import noSpace = Formatting.noSpace;
import newLine = Formatting.newLine;
Expand Down Expand Up @@ -149,6 +149,10 @@ export class SafeDSFormatter extends AbstractFormatter {
this.formatSdsMemberType(node);
} else if (ast.isSdsCallableType(node)) {
this.formatSdsCallableType(node);
} else if (ast.isSdsLiteralType(node)) {
this.formatSdsLiteralType(node);
} else if (ast.isSdsLiteralList(node)) {
this.formatSdsLiteralList(node);
} else if (ast.isSdsNamedType(node)) {
this.formatSdsNamedType(node);
} else if (ast.isSdsUnionType(node)) {
Expand Down Expand Up @@ -761,6 +765,25 @@ export class SafeDSFormatter extends AbstractFormatter {
formatter.keyword('->').surround(oneSpace());
}

private formatSdsLiteralType(node: ast.SdsLiteralType): void {
const formatter = this.getNodeFormatter(node);

formatter.keyword('literal').append(noSpace());
}

private formatSdsLiteralList(node: ast.SdsLiteralList): void {
const formatter = this.getNodeFormatter(node);
const literals = node.literals ?? [];

if (literals.length > 0) {
formatter.node(literals[0]).prepend(noSpace());
formatter.nodes(...literals.slice(1)).prepend(oneSpace());
}

formatter.keywords(',').prepend(noSpace());
formatter.keyword('>').prepend(noSpace());
}

private formatSdsNamedType(node: ast.SdsNamedType) {
const formatter = this.getNodeFormatter(node);

Expand Down Expand Up @@ -847,10 +870,12 @@ export class SafeDSFormatter extends AbstractFormatter {

if (ast.isSdsCallableType(node) || ast.isSdsMemberType(node)) {
return true;
} else if (ast.isSdsUnionType(node)) {
return typeArgumentsOrEmpty(node.typeArgumentList).length > 0;
} else if (ast.isSdsLiteralType(node)) {
return literalsOrEmpty(node).length > 0;
} else if (ast.isSdsNamedType(node)) {
return typeArgumentsOrEmpty(node.typeArgumentList).length > 0;
} else if (ast.isSdsUnionType(node)) {
return typeArgumentsOrEmpty(node.typeArgumentList).length > 0;
} else {
return false;
}
Expand Down
25 changes: 25 additions & 0 deletions DSL/src/language-server/grammar/safe-ds.langium
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@ SdsType returns SdsType:

SdsPrimaryType returns SdsType:
SdsCallableType
| SdsLiteralType
| SdsNamedType
| SdsUnionType
;
Expand All @@ -854,6 +855,29 @@ SdsCallableType returns SdsCallableType:
resultList=SdsResultList
;

interface SdsLiteralType extends SdsType {
literalList: SdsLiteralList
}

SdsLiteralType returns SdsLiteralType:
'literal' literalList=SdsLiteralList
;

interface SdsLiteralList extends SdsObject {
literals: SdsLiteral[]
}

SdsLiteralList returns SdsLiteralList:
{SdsLiteralList}
(LESS_THAN | CALL_TYPE_ARGUMENT_LIST_START)
(
literals+=SdsLiteral
(',' literals+=SdsLiteral)*
','?
)?
'>'
;

interface SdsNamedType extends SdsType {
declaration: @SdsNamedTypeDeclaration
typeArgumentList?: SdsTypeArgumentList
Expand Down Expand Up @@ -1038,6 +1062,7 @@ terminal CALL_TYPE_ARGUMENT_LIST_START:
( '*' // Star projection as positional type argument
| 'in' // Contravariant type projection as positional type argument
| 'out' // Covariant type projection as positional type argument
| 'literal' // Invariant literal type as positional type argument
| 'union' // Invariant union type as positional type argument
| '>' // Empty type argument list
| ID /\s*/
Expand Down
8 changes: 4 additions & 4 deletions DSL/src/language-server/helpers/astShortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {
isSdsDeclaration,
SdsAnnotatedObject,
SdsAnnotationCall,
SdsClass,
SdsObject,
SdsLiteral,
SdsLiteralType,
SdsTypeArgument,
SdsTypeArgumentList,
} from '../generated/ast';
Expand All @@ -17,8 +17,8 @@ export const annotationCallsOrEmpty = function (node: SdsAnnotatedObject): SdsAn
}
};

export const classMembersOrEmpty = function (node: SdsClass): SdsObject[] {
return node.body?.members ?? [];
export const literalsOrEmpty = function (node: SdsLiteralType | undefined): SdsLiteral[] {
return node?.literalList?.literals ?? [];
};

export const typeArgumentsOrEmpty = function (node: SdsTypeArgumentList | undefined): SdsTypeArgument[] {
Expand Down
78 changes: 0 additions & 78 deletions DSL/syntaxes/safe-ds.tmLanguage.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
segment s(
f: literal<1.0 , null , >
) {}

// -----------------------------------------------------------------------------

segment s(
f: literal<1.0, null,>
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
segment mySegment(x: literal < >) {}

// -----------------------------------------------------------------------------

segment mySegment(x: literal<>) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
segment mySegment(
x: literal < 1.0 , null >
) {}

// -----------------------------------------------------------------------------

segment mySegment(
x: literal<1.0, null>
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
segment mySegment(
x: literal < > . InnerClass
) {}

// -----------------------------------------------------------------------------

segment mySegment(
x: literal<>.InnerClass
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
segment mySegment(
x: literal < > . InnerClass ?
) {}

// -----------------------------------------------------------------------------

segment mySegment(
x: literal<>.InnerClass?
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// $TEST$ syntax_error

class literal
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ no_syntax_error

segment s(
f: literal<true, false, >
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ syntax_error

segment mySegment(
x: literal<literal<>>
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ syntax_error

segment mySegment(
x: literal<
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ no_syntax_error

segment mySegment(
x: literal<>
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ no_syntax_error

segment mySegment(
x: literal<null, true, false, 1, 1.0, "s">
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ syntax_error

segment mySegment(
x: OuterClass.literal<>
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ no_syntax_error

segment mySegment(
x: literal<>.InnerClass
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// $TEST$ no_syntax_error

segment mySegment(
x: literal<>.InnerClass?
) {}
1 change: 1 addition & 0 deletions DSL/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export default defineConfig({
include: ['src'],
exclude: ['**/generated'],
},
exclude: ['out'],
},
});