Skip to content

Commit 17ec03c

Browse files
committed
2nd attempt to fix partial completion (#2147)
# Conflicts: # package-lock.json
1 parent 9e89fd8 commit 17ec03c

4 files changed

Lines changed: 60 additions & 16 deletions

File tree

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/langium/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"dependencies": {
6868
"@chevrotain/regexp-to-ast": "~12.0.0",
6969
"chevrotain": "~12.0.0",
70-
"chevrotain-allstar": "~0.4.2",
70+
"chevrotain-allstar": "~0.4.3",
7171
"vscode-languageserver": "~9.0.1",
7272
"vscode-languageserver-textdocument": "~1.0.11",
7373
"vscode-uri": "~3.1.0"

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export abstract class AbstractLangiumParser implements BaseParser {
138138
protected allRules = new Map<string, RuleResult>();
139139
protected mainRule!: RuleResult;
140140

141-
constructor(services: LangiumCoreServices) {
141+
constructor(services: LangiumCoreServices, incomplete: boolean) {
142142
this.lexer = services.parser.Lexer;
143143
const tokens = this.lexer.definition;
144144
const production = services.LanguageMetaData.mode === 'production';
@@ -147,13 +147,13 @@ export abstract class AbstractLangiumParser implements BaseParser {
147147
...services.parser.ParserConfig,
148148
skipValidations: production,
149149
errorMessageProvider: services.parser.ParserErrorMessageProvider
150-
}, services.shared.profilers.LangiumProfiler.createTask('parsing', services.LanguageMetaData.languageId));
150+
}, incomplete, services.shared.profilers.LangiumProfiler.createTask('parsing', services.LanguageMetaData.languageId));
151151
} else {
152152
this.wrapper = new ChevrotainWrapper(tokens, {
153153
...services.parser.ParserConfig,
154154
skipValidations: production,
155155
errorMessageProvider: services.parser.ParserErrorMessageProvider
156-
});
156+
}, incomplete);
157157
}
158158
}
159159

@@ -223,7 +223,7 @@ export class LangiumParser extends AbstractLangiumParser {
223223
}
224224

225225
constructor(services: LangiumCoreServices) {
226-
super(services);
226+
super(services, false);
227227
this.linker = services.references.Linker;
228228
this.converter = services.parser.ValueConverter;
229229
this.astReflection = services.shared.AstReflection;
@@ -694,6 +694,10 @@ export class LangiumCompletionParser extends AbstractLangiumParser {
694694
private nextTokenIndex = 0;
695695
private stackSize = 0;
696696

697+
constructor(services: LangiumCoreServices) {
698+
super(services, true);
699+
}
700+
697701
action(): void {
698702
// NOOP
699703
}
@@ -809,15 +813,16 @@ class ChevrotainWrapper extends EmbeddedActionsParser {
809813
// This array is set in the base implementation of Chevrotain.
810814
definitionErrors: IParserDefinitionError[];
811815

812-
constructor(tokens: TokenVocabulary, config: IParserConfig) {
816+
constructor(tokens: TokenVocabulary, config: IParserConfig, incomplete: boolean) {
813817
const useDefaultLookahead = config && 'maxLookahead' in config;
814818
super(tokens, {
815819
...defaultConfig,
816820
lookaheadStrategy: useDefaultLookahead
817821
? new LLkLookaheadStrategy({ maxLookahead: config.maxLookahead })
818822
: new LLStarLookaheadStrategy({
819823
// If validations are skipped, don't log the lookahead warnings
820-
logging: config.skipValidations ? () => { } : undefined
824+
logging: config.skipValidations ? () => { } : undefined,
825+
incomplete,
821826
}),
822827
...config,
823828
});
@@ -867,8 +872,8 @@ class ChevrotainWrapper extends EmbeddedActionsParser {
867872

868873
class ProfilerWrapper extends ChevrotainWrapper {
869874
private readonly task: ProfilingTask;
870-
constructor(tokens: TokenVocabulary, config: IParserConfig, task: ProfilingTask) {
871-
super(tokens, config);
875+
constructor(tokens: TokenVocabulary, config: IParserConfig, incomplete: boolean, task: ProfilingTask) {
876+
super(tokens, config, incomplete);
872877
this.task = task;
873878
}
874879

packages/langium/test/parser/langium-parser-builder.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,45 @@ describe('ALL(*) parser', () => {
924924
expect(result.parserErrors).toHaveLength(0);
925925
expect(result.value.$type).toBe('B');
926926
});
927+
928+
test('Can perform partial outer context resolution', async () => {
929+
const outerContextGrammar = `
930+
entry Model: items+=Stmt*;
931+
Stmt: 'ensure' expr=Additive;
932+
933+
Additive infers Expression:
934+
Multiplicative
935+
(({infer Add.left=current} '+' | {infer Sub.left=current} '-') right=Multiplicative)*;
936+
937+
Multiplicative infers Expression:
938+
Primary
939+
(({infer Mul.left=current} '*' | {infer Div.left=current} '/') right=Primary)*;
940+
941+
Primary infers Expression:
942+
RefExpression | NumberLiteral;
943+
944+
RefExpression:
945+
target=PathOrMetadataAccess;
946+
947+
NumberLiteral:
948+
value=NUMBER;
949+
950+
PathOrMetadataAccess returns string:
951+
PATH | MetadataAccess;
952+
953+
// '/' inside PATH collides with '/' as division operator
954+
PATH returns string:
955+
ID | (ID ('/' ID)* ':' ID);
956+
957+
terminal MetadataAccess: /@[_a-zA-Z][\\w_-]*/;
958+
terminal NUMBER: /[0-9]+(\\.[0-9]+)?/;
959+
terminal ID: /[_a-zA-Z][\\w_-]*/;
960+
hidden terminal WS: /\\s+/;`;
961+
const parser = await parserFromGrammar(outerContextGrammar);
962+
const result = parser.parse('ensure someOtherNumber / 10');
963+
expect(result.lexerErrors).toHaveLength(0);
964+
expect(result.parserErrors).toHaveLength(0);
965+
});
927966
});
928967

929968
describe('Parsing actions', () => {

0 commit comments

Comments
 (0)