使用语言服务器协议以编程方式转到定义

发布于 2025-01-22 23:58:22 字数 2298 浏览 5 评论 0 原文

我已经创建了自己的 XTEXT 基于DSL和 vscode 基于语言服务器协议的编辑器。我在单独的文件中创建多个模型:

# filename dummy1.xyz
model { name dummy1
   elements {
      Elem { name elem1 }
   }
}}

有一个构图文件引用这些元素(例如在不同的标头文件中调用函数),

# filename composedmodel.abc
composedModel {
   elemCalls {
      ElemCall { elem "dummy1.elem1" }
   } 
}

如果我单击“ dummy1.elem1”, vscode 打开一个新文件定义ELEM1的位置。我想以编程方式复制相同的行为。

为此,我用 elemcall 时,我都会从LSP客户端发送以下命令,

public async enterRuleElemCall(ctx: RuleElemCallContext): Promise<void> {
    var resp = this.client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type,
            this.client.code2ProtocolConverter.asTextDocumentPositionParams(this.document, new vscode.Position(2, 45)))
                .then(this.client.protocol2CodeConverter.asDefinitionResult, (error) => {
                    return this.client.handleFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error, null);
            });

如您所见,为了测试目的,我有硬编码 new Vscode.position.position.position.position.posity(2,45)通常是从光标位置获得的。

我有两个问题:

  1. 如何获得“ dummy1.elem1”的位置?
  2. 即使有硬编码的位置,我得到的响应是对引用对象的定义的文件的URI,而不是其定义的位置。如何仅提取相关的部分
    Elem { name elem1 }

编辑1:

通过将响应作为 locationlink

var location = resp as unknown as LocationLink[];
        
console.log(location[0]);
console.log(location[0].targetUri);
console.log(location[0].targetRange);

for location> location [0]

$ {uri: v, range: $}
range:$ {_start: $, _end: $}
uri:v {scheme: 'file', authority: '', path: '/home/user/dummy1.xyz', query: '', fragment: '', …}

得到是未定义

编辑2: 我终于能够使用以下代码提取路径:

let location = JSON.parse(JSON.stringify(resp));
console.log(location[0].uri.path);

为什么 targeturi 不确定的?我问,因为如果我

var location = resp as unknown as DocumentLink[];

不再未定义,那么我是否将resp打字为 ,但 target 仍然不确定。

I have created my own Xtext based DSL and vscode based editor with language server protocol. I create multiple models in separate files:

# filename dummy1.xyz
model { name dummy1
   elements {
      Elem { name elem1 }
   }
}}

There is a composition file which references these elements (like calling a function declared in different header files)

# filename composedmodel.abc
composedModel {
   elemCalls {
      ElemCall { elem "dummy1.elem1" }
   } 
}

If I click on "dummy1.elem1", vscode opens a new file where the elem1 is defined. I want to replicate the same behavior programmatically.

For that, I parse these composed model files with antlr4ts. I send the following command from the LSP client whenever I encounter ElemCall

public async enterRuleElemCall(ctx: RuleElemCallContext): Promise<void> {
    var resp = this.client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type,
            this.client.code2ProtocolConverter.asTextDocumentPositionParams(this.document, new vscode.Position(2, 45)))
                .then(this.client.protocol2CodeConverter.asDefinitionResult, (error) => {
                    return this.client.handleFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error, null);
            });

As you can see, for testing purpose I have hard-coded new vscode.Position(2, 45) which is usually obtained from the cursor position.

I have 2 questions:

  1. How can I get this position of "dummy1.elem1"?
  2. Even with the hard-coded position, the response I get is the URI to the file in which the referenced object is defined, but not the position of its definition. How can I extract only the relevant section
    Elem { name elem1 }

Edit 1:

By typecasting response as LocationLink

var location = resp as unknown as LocationLink[];
        
console.log(location[0]);
console.log(location[0].targetUri);
console.log(location[0].targetRange);

For location[0] I get

$ {uri: v, range: $}
range:$ {_start: $, _end: $}
uri:v {scheme: 'file', authority: '', path: '/home/user/dummy1.xyz', query: '', fragment: '', …}

But rest of the two it is undefined

Edit 2:
I am finally able to extract the path with the following code:

let location = JSON.parse(JSON.stringify(resp));
console.log(location[0].uri.path);

Any ideas why targetUri is undefined? I ask because if I typecast resp as

var location = resp as unknown as DocumentLink[];

the range is not undefined anymore, but target is still undefined.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文