2KB项目,专业的源码交易网站 帮助 收藏 每日签到

编程语言服务器协议

  • 时间:2019-01-23 18:23 编辑:2KB 来源:2KB.COM 阅读:577
  • 扫一扫,手机访问
  • 分享
摘要: 英文原文:Lan
英文原文:Language Server Protocol

上个月,Apple 在 Swift.org 论坛上宣布,它正在开始采用 Swift 和 C 语言的语言服务器协议(LSP)

在 Apple,我们优先考虑为所有 Swift 开发者提供高质量的工具,包括那些在不在 Apple 平台上开发的开发者。我们希望和开源社区合作并且集中精力建设可以由 Xcode 和其他编辑器和平台共享的公共基础设施,因此,我们选择采用 LSP。

Argyrios Kyrtzidis,2018年10月15日

这可以说是自 2014 年 Swift 开源发布以来苹果公司对 Swift 做出的最重要的决定。这是苹果应用开发者的大事件,更是在其它平台的 Swift 开发者的大事件。

为什么这件事情这么重要?本文会对语言服务协议进行介绍,讲解它能解决什么问题,如何解决这些问题,以及可能会带来什么样的长期影响。

我们假设有这样一个表格,它的行代表不同的编程语言(Swift、JavaScript、Ruby、Python 等),每一列代表不同的代码编辑器(XCode、Visual Studio、Vim、Atom 等)。这样一来,表内的每个单元格都表示某个编辑器对某种语言的支持程度。

现在,你会发现不同的组合之间兼容性很差。有一些编辑器对少数几种语言进行了深度集成,几乎不支持任何其他语言,也有一些编辑器则致力于支持语言的通用特性,对大量的语言进行了较为浅层的支持。(IDE 通常是指前者。)

举例来说,不使用 XCode 开发苹果应用是件很难理解的事情,而使用 XCode 开发其它东西简直就是傻

为了让编辑器对语言支持得更好,它需要编写集成语言特性的代码 —— 直接在项目代码中编写,或者采用插件系统的方式。语言和编辑器之间会存在差异,比如在 Vim 中改进了对 Ruby 的支持并不能同时让 Vim 对 Python 支持得更好,也不能让 Ruby 在 Atom 中更好地工作。结果就是:对各种技术之的支持不能达成一致,会浪费大量的精力。

这里描述的情况通常被称为 M × N 问题,它要处理的问题数是 M 种编辑器和 N 语言的乘积。语言服务协议要做的就是把 M × N 的问题变成 M + N 的问题。

编辑器不用支持每一种语言,只需要支持 LSP。然后,所有支持 LSP 的语言都会在这个编辑器中得到相同级别的支持。

Tomohiro Matsuyama 在 2010 年写了一篇标题为 “Emacs は死んだ” (“Emacs 已死”) 的文章,对这个问题进行了很好地总结。Matsuyama 在描述 Emacs 脚本语言的局限(没有多线程、低层次的 API 少、用户群不大)时提出他的观点。他认为插件应该与外部程序接口,而不应该是本地实现。

语言服务器协议对其支持的语言提供了一系列通用的功能,包括:

  • 语法高亮

  • 自动格式化

  • 自动完成

  • 语法(检查)

  • 提示

  • 内部诊断

  • 跳转到定义

  • 在项目中查找引用

  • 高级文本或符合搜索

在 LSP 的支持下,工具和编辑器可以更加专注于处理可用性和高级功能,而不需要为每个新技术做重复性的工作。

语言服务协议是怎么起作用的

如果你是 iOS 开发者,你可能最熟悉的“服务”和“协议”概念是建立在 Web 应用基于 HTTP 和 JSON 的通信技术之上。这实际上与语言服务协议如何工作并没多大关系。

对于 LSP 来说,客户端就是编辑器 —— 或者更普适性的说法是工具 —— 而服务端是指运行在本地另一个进程中的外部程序。

作为协议本身,LSP 有点像 HTTP 的简单版:

  • 每个消息都包含头和内容两个部分。

  • 头部需要用 Content-Length 参数来描述内容部分的字节数,以及可选的 Content-Type 参数(默认是 application/vscode-jsonrpc; charset=utf-8

  • 内容部分是请求、响应和通知的内容,其数据结构遵循 JSON-RPC 规范。

一旦工具有变化,比如用户条到了一个标记的定义之类的,工具都会向服务端发送一个请求。服务端收到这个请求之后返回对应的响应。

例如,想象一下用户在一个支持编程语言服务协议的类Xcode的编辑器中打开如下Swfit代码:

Swift

class Parent {}
class Child: Parent {}

当用户 ?-单击第二行的继承语句中的 Parent 标记的时候,编辑器跳到了第一行的 Parent  类定义处。

以下是LSP如何在银幕背后让这个交互实现的:

首先,当用户打开 Swfit 代码的时候,编辑器在一个单独的进程中启动了他的 Swift语言服务器,如果没有运行起来的话,会实施一些额外的设置。

当用户执行 “跳转到定义” 的命令时,编辑器将如下请求发送到 Swift语言服务器:

JSON

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "textDocument/definition",
  "params": {
    "textDocument": {
      "uri": "file:///Users/NSHipster/Example.swift"
    },
    "position": {
      "line": 1,
      "character": 13
    }
  }
}

收到这个请求之后, Swift 语言服务使用像 SourceKit 这样的编译工具把代码实体标识出来,并在前面的代码中查找其声明位置。语言服务随后响应这样的消息:

JSON

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "uri": "file:///Users/NSHipster/Example.swift",
    "range": {
      "start": {
        "line": 0,
        "character": 6
      },
      "end": {
        "line": 0,
        "character": 12
      }
    }
  }
}

 最后,编辑器导航到相应的文件(示例中就是打开的这个文件),将光标移动到响应指示的位置,把标识高亮显示出来。

这种方法的美妙之处在于编辑器在做这些事情的时候,不需要知道任何与 Swift 编译语言相关的事情,它在乎 .swift 文件与 Swift 代码之间的关联。编辑器需要做的事情就是与语言服务对话,并更新 UI。只要编辑器能做这件事情,那就可以按照相同的处理过程,实现任意语言的代码与相应的语言服务之间进行交互。

Clang/LLVM的语言服务协议支持

如果上面的M + N的图看起来很熟悉,可能是因为LLVM采用了相同的方法。

LLVM的核心是一个中间表示(IR)。支持的语言使用前端编译器生成IR,然后该IR可以生成任何后端编译器所支持的平台的机器码。

如果你对关于Swift代码如何编译感兴趣,请阅读我们关于SwiftSyntax的文章

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
上一篇:CSS 架构
下一篇:CSS 架构
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部