diff --git a/packages/langium/src/lsp/completion/follow-element-computation.ts b/packages/langium/src/lsp/completion/follow-element-computation.ts index f34bbc1ea..32590f5dd 100644 --- a/packages/langium/src/lsp/completion/follow-element-computation.ts +++ b/packages/langium/src/lsp/completion/follow-element-computation.ts @@ -52,7 +52,9 @@ function findNextFeaturesInternal(options: { next: NextFeature, cardinalities: M const feature = next.feature; if (visited.has(feature)) { return []; - } else { + } else if (!ast.isGroup(feature)) { + // Do not add the feature to the list if it is a group + // `findFirstFeaturesInternal` will take care of this visited.add(feature); } let parent: ast.Group | undefined; @@ -132,8 +134,6 @@ function findFirstFeaturesInternal(options: { next: NextFeature, cardinalities: } else { visited.add(feature); } - } - if (ast.isGroup(feature)) { return findNextFeaturesInGroup(next as NextFeature, 0, cardinalities, visited, plus) .map(e => modifyCardinality(e, feature.cardinality, cardinalities)); } else if (ast.isAlternatives(feature) || ast.isUnorderedGroup(feature)) { diff --git a/packages/langium/test/lsp/completion-provider.test.ts b/packages/langium/test/lsp/completion-provider.test.ts index 4bbd2e9be..9fcdb6a25 100644 --- a/packages/langium/test/lsp/completion-provider.test.ts +++ b/packages/langium/test/lsp/completion-provider.test.ts @@ -131,7 +131,35 @@ describe('Completion within alternatives', () => { expectedItems: ['c', 'd'] }); }); + test('Should show correct keywords in completion of group', async () => { + const grammar = ` + grammar g + entry Main: ('a' a+=ID | 'b' b+=ID | 'c' c+=ID)*; + hidden terminal WS: /\\s+/; + terminal ID: /\\w+/; + `; + + const services = await createServicesForGrammar({ grammar }); + const completion = expectCompletion(services); + const text = '<|>a id1 <|>b id2 <|>c id3'; + + await completion({ + text, + index: 0, + expectedItems: ['a', 'b', 'c'] + }); + await completion({ + text, + index: 1, + expectedItems: ['a', 'b', 'c'] + }); + await completion({ + text, + index: 2, + expectedItems: ['a', 'b', 'c'] + }); + }); test('Should show correct cross reference and keyword in completion', async () => { const grammar = `