我已经用语言服务器协议创建了我自己的基于Xtext
的DSL和基于vscode
的编辑器。我用antlr4ts从当前的TextDocument
中解析模型。下面是侦听器
class TreeShapeListener implements DebugInternalModelListener {
public async enterRuleElem1(ctx: RuleElem1Context): Promise<void> {
...
// by the time the response is received, 'walk' function returns
var resp = await this.client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type,
this.client.code2ProtocolConverter.asTextDocumentPositionParams(this.document, position))
.then(this.client.protocol2CodeConverter.asDefinitionResult, (error) => {
return this.client.handleFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error, null);
});
...
this.model.addElem1(elem1);
}
public async enterRuleElem2(ctx: RuleElem2Context): void {
...
this.model.addElem2(elem2);
}
,这里我创建了解析器和树遍历器
// Create the lexer and parser
let inputStream = antlr4ts.CharStreams.fromString(document.getText());
let lexer = new DebugInternaModelLexer(inputStream);
let tokenStream = new antlr4ts.CommonTokenStream(lexer);
let parser = new DebugInternalModelParser(tokenStream);
parser.buildParseTree = true;
let tree = parser.ruleModel();
let model = new Model();
ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(model, client, document) as ParseTreeListener, tree);
console.log(model);
问题是,在处理其中一个规则(enterRuleElem1
)时,我有一个async函数(client.sendRequest
),在ParseTreeWalker.DEFAULT.walk
返回后返回。如何让walk
等到所有规则完成?
编辑1:不确定这是否是walk
函数的工作方式,但试图用
function setTimeoutPromise(delay) {
return new Promise((resolve, reject) => {
if (delay < 0) return reject("Delay must be greater than 0")
setTimeout(() => {
resolve(`You waited ${delay} milliseconds`)
}, delay)
})
}
async function enterRuleBlah() {
let resp = await setTimeoutPromise(2500);
console.log(resp);
}
function enterRuleBlub() {
console.log('entered blub');
}
function walk() {
enterRuleBlah();
enterRuleBlub();
}
walk();
console.log('finished parsing');
,输出为
entered blub
finished parsing
You waited 2500 milliseconds
编辑2:我尝试了答案中的建议,现在它有效了!我的解决方案如下:
public async doStuff() {
...
return new Promise((resolve)=> {
resolve(0);
})
}
let listener = new TreeShapeListener(model, client, document);
ParseTreeWalker.DEFAULT.walk(listener as ParseTreeListener, tree);
await listener.doStuff();
无论您是否将侦听器/访问者规则设置为异步,树遍历都是完全同步的。最好将请求从walk中分离出来,walk应该只收集所有需要知道发送什么和之后的的信息。处理此集合并实际发送请求,然后您可以等待。