Skip to content

Commit 51f5d0a

Browse files
authored
Fix infix rule CST issues (#2023)
Fix infix operator CST issues
1 parent 3670747 commit 51f5d0a

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

packages/langium/src/parser/cst-node-builder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ export class CstNodeBuilder {
8787
}
8888
}
8989

90-
construct(item: { $type: string | symbol | undefined, $cstNode: CstNode }): void {
90+
construct(item: { $type: string | symbol | undefined, $cstNode: CstNode, $infix?: boolean }): void {
9191
const current: CstNode = this.current;
92-
// The specified item could be a datatype ($type is symbol) or a fragment ($type is undefined)
92+
// The specified item could be a datatype ($type is symbol), fragment ($type is undefined) or infix rule ($infix is true)
9393
// Only if the $type is a string, we actually assign the element
94-
if (typeof item.$type === 'string') {
94+
if (typeof item.$type === 'string' && !item.$infix) {
9595
this.current.astNode = <AstNode>item;
9696
}
9797
item.$cstNode = current;

packages/langium/src/parser/langium-parser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface DataTypeNode {
4141
}
4242

4343
interface InfixElement {
44+
$infix: true;
4445
$type: string;
4546
$cstNode: CompositeCstNode;
4647
parts: AstNode[];
@@ -512,12 +513,14 @@ export class LangiumParser extends AbstractLangiumParser {
512513

513514
// Create sub-expressions
514515
const leftInfix: InfixElement = {
516+
$infix: true,
515517
$type: obj.$type,
516518
$cstNode: obj.$cstNode,
517519
parts: leftParts,
518520
operators: leftOperators
519521
};
520522
const rightInfix: InfixElement = {
523+
$infix: true,
521524
$type: obj.$type,
522525
$cstNode: obj.$cstNode,
523526
parts: rightParts,

packages/langium/test/lsp/goto-definition.test.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { describe, test } from 'vitest';
88
import { EmptyFileSystem } from 'langium';
9-
import { createLangiumGrammarServices } from 'langium/grammar';
9+
import { createLangiumGrammarServices, createServicesForGrammar } from 'langium/grammar';
1010
import { expectGoToDefinition } from 'langium/test';
1111

1212
/**
@@ -114,3 +114,64 @@ describe('Definition Provider', () => {
114114
});
115115
});
116116
});
117+
118+
describe('Definition Provider with Infix Operators', async () => {
119+
120+
const infixGrammar = `
121+
grammar Test
122+
entry Model: elements+=Element*;
123+
Element: Statement | Item;
124+
Item: 'item' name=ID ';';
125+
126+
Statement: value=InfixExpr ';';
127+
128+
infix InfixExpr on Primary:
129+
'*' | '/'
130+
> '+' | '-';
131+
132+
Primary: '(' InfixExpr ')' | {infer ItemRef} ref=[Item];
133+
134+
terminal ID: /\\w+/;
135+
hidden terminal WS: /\\s+/;
136+
hidden terminal COMMENT: /\\/\\/.*/;
137+
`;
138+
139+
const infixServices = await createServicesForGrammar({ grammar: infixGrammar });
140+
const gotoDefinitionInfix = expectGoToDefinition(infixServices);
141+
142+
test('Simple infix operator expression should find Item from reference', async () => {
143+
await gotoDefinitionInfix({
144+
text: `
145+
item <|a|>;
146+
<|>a;
147+
`,
148+
index: 0,
149+
rangeIndex: 0
150+
});
151+
});
152+
153+
test('Complex infix operator expression should find Item from reference', async () => {
154+
const text = `
155+
item <|a|>;
156+
item <|b|>;
157+
item <|c|>;
158+
<|>a + <|>b * <|>c;
159+
`;
160+
await gotoDefinitionInfix({
161+
text,
162+
index: 0,
163+
rangeIndex: 0
164+
});
165+
await gotoDefinitionInfix({
166+
text,
167+
index: 1,
168+
rangeIndex: 1
169+
});
170+
await gotoDefinitionInfix({
171+
text,
172+
index: 2,
173+
rangeIndex: 2
174+
});
175+
});
176+
177+
});

0 commit comments

Comments
 (0)