Skip to content
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
6 changes: 3 additions & 3 deletions packages/langium/src/parser/cst-node-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ export class CstNodeBuilder {
}
}

construct(item: { $type: string | symbol | undefined, $cstNode: CstNode }): void {
construct(item: { $type: string | symbol | undefined, $cstNode: CstNode, $infix?: boolean }): void {
const current: CstNode = this.current;
// The specified item could be a datatype ($type is symbol) or a fragment ($type is undefined)
// The specified item could be a datatype ($type is symbol), fragment ($type is undefined) or infix rule ($infix is true)
// Only if the $type is a string, we actually assign the element
if (typeof item.$type === 'string') {
if (typeof item.$type === 'string' && !item.$infix) {
this.current.astNode = <AstNode>item;
}
item.$cstNode = current;
Expand Down
3 changes: 3 additions & 0 deletions packages/langium/src/parser/langium-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface DataTypeNode {
}

interface InfixElement {
$infix: true;
$type: string;
$cstNode: CompositeCstNode;
parts: AstNode[];
Expand Down Expand Up @@ -512,12 +513,14 @@ export class LangiumParser extends AbstractLangiumParser {

// Create sub-expressions
const leftInfix: InfixElement = {
$infix: true,
$type: obj.$type,
$cstNode: obj.$cstNode,
parts: leftParts,
operators: leftOperators
};
const rightInfix: InfixElement = {
$infix: true,
$type: obj.$type,
$cstNode: obj.$cstNode,
parts: rightParts,
Expand Down
63 changes: 62 additions & 1 deletion packages/langium/test/lsp/goto-definition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { describe, test } from 'vitest';
import { EmptyFileSystem } from 'langium';
import { createLangiumGrammarServices } from 'langium/grammar';
import { createLangiumGrammarServices, createServicesForGrammar } from 'langium/grammar';
import { expectGoToDefinition } from 'langium/test';

/**
Expand Down Expand Up @@ -114,3 +114,64 @@ describe('Definition Provider', () => {
});
});
});

describe('Definition Provider with Infix Operators', async () => {

const infixGrammar = `
grammar Test
entry Model: elements+=Element*;
Element: Statement | Item;
Item: 'item' name=ID ';';

Statement: value=InfixExpr ';';

infix InfixExpr on Primary:
'*' | '/'
> '+' | '-';

Primary: '(' InfixExpr ')' | {infer ItemRef} ref=[Item];

terminal ID: /\\w+/;
hidden terminal WS: /\\s+/;
hidden terminal COMMENT: /\\/\\/.*/;
`;

const infixServices = await createServicesForGrammar({ grammar: infixGrammar });
const gotoDefinitionInfix = expectGoToDefinition(infixServices);

test('Simple infix operator expression should find Item from reference', async () => {
await gotoDefinitionInfix({
text: `
item <|a|>;
<|>a;
`,
index: 0,
rangeIndex: 0
});
});

test('Complex infix operator expression should find Item from reference', async () => {
const text = `
item <|a|>;
item <|b|>;
item <|c|>;
<|>a + <|>b * <|>c;
`;
await gotoDefinitionInfix({
text,
index: 0,
rangeIndex: 0
});
await gotoDefinitionInfix({
text,
index: 1,
rangeIndex: 1
});
await gotoDefinitionInfix({
text,
index: 2,
rangeIndex: 2
});
});

});
Loading