做者:Mattt,原文连接
原文日期:2018-11-19
html
上个月,苹果公司 在 Swift.org 论坛上宣布,正在着手为 Swift 和 C 语言支持 Language Server Protocol(语言服务器协议,LSP)。ios
对于苹果公司而言,为全部 Swift 开发者 —— 包括非苹果平台上的 —— 提供高质量的工具支持很是重要。咱们但愿与开源社区合做,将精力集中在构建 Xcode 和其余编辑器、其余平台能够共享的公共基础设施上。为实现这一目标,[……],咱们决定支持 LSP。git
Argyrios Kyrtzidis,2018 年 10 月 15 日程序员
这多是苹果自 2014 年将 Swift 做为开源软件发布以来,为 Swift 作出的最重要的决定。 这对于 APP 开发者来讲是一件大事,对于其余平台上的 Swift 开发者来讲更是一件大事。github
为了理解其中的缘由,本周的文章将研究 Language Server Protocol 解决了什么问题,它是如何工做的,以及它的长期影响多是什么。编程
更新:sourcekit-lsp 项目如今已经能够 在 GitHub 上访问 了。json
想象这样一个矩阵,每一行表示不一样的编程语言(Swift、JavaScript、Ruby、Python 等),每一列表示不一样的代码编辑器(Xcode、Visual Studio、Vim、Atom 等),这样每一个单元格表示特定编辑器对一种语言的支持级别。swift
而后,你就发现各类组合造成了一种支离破碎的兼容。有些编辑器和部分语言深度集成,但除此以外几乎什么都干不了;其余编辑器则比较通用,对不少语言都提供了基本的支持。(IDE 这个术语一般用来描述前者。)后端
举个奇葩的例子:你不用 Xcode 来开发 APP,却偏用来干其余事情。
为了更好地支持某一特定的语言,编辑器必须编写一些集成代码(integration code)—— 要么直接写在项目里,要么经过插件。因为不一样语言和编辑器的实现机制不同,所以比方说 Vim 改进了对 Ruby 支持,但这并不能让它更好地支持 Python,也不能让 Ruby 在 Atom 上运行地更好。最终的结果是:大量精力浪费在了不一样技术的兼容上。
咱们上面描述的状况一般被称为 M × N 问题,即最终的集成方案数量为编译器数量 M 与语言数量 N 的乘积。Language Server Protocol 所作的事情就是将 M × N 问题变成 M + N 问题。
编辑器没必要实现对每种语言的支持,只需支持 LSP 便可。以后,它就能同等程度地支持全部支持 LSP 的语言。
Tomohiro Matsuyama 在 2010 年写的 "Emacs は死んだ" ("Emacs 已死") 这篇文章就对这种问题作出了一个很好的论述。Matsuyama 描述了 Emacs 脚本语言的局限性(不支持多线程、底层 API 过少、用户基数过小),他认为编写插件的首选方法应该是与外部程序进行交互,而不是原生实现。
Language Server Protocol 为支持的语言提供了一套通用的功能集,包括:
各类工具和编辑器能够将精力用于提高可用性和提供更高级的功能,而不是为每种新技术再造个轮子。
若是你是一个 iOS 程序员,那么必定很熟悉 server 和 protocol 这两个术语在 Web 应用程序的 HTTP + JSON 通讯场景下的含义。实际上 Language Server Protocol 差很少也是这么工做的。
对于 LSP,client 是指编辑器 —— 或者更宽泛一点,是指工具,server 是指本地独立进程里运行的一个外部程序。
至于名字中包含 protocol,是由于 LSP 相似于一个精简版的 HTTP:
Content-Length
字段,用于说明内容部分的大小(以字节为单位),以及一个可选的 Content-Type
字段(默认值为 application/vscode-jsonrpc; charset=utf-8
)。每当工具中发生了什么事情,好比用户须要跳转到符号的定义,工具就会向 server 发送一个请求。server 接收到该请求,而后返回适当的响应。
class Parent {}
class Child: Parent {}
复制代码
如下是 LSP 如何在幕后实现这种交互:
首先,当用户打开 Swift 代码时,若 Swift language server 并未运行,编辑器将在一个独立进程中启动它,并执行一些额外的配置。
当用户执行 "跳转到定义(jump to definition)" 指令时,编辑器向 Swift language server 发送如下请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "textDocument/definition",
"params": {
"textDocument": {
"uri": "file:///Users/NSHipster/Example.swift"
},
"position": {
"line": 1,
"character": 13
}
}
}
复制代码
收到这个请求后,Swift language server 使用 SourceKit 等编译器工具来标识相应的代码实体,并在代码的上一行找到其声明的位置。而后 language server 用如下消息进行响应:
{
"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 编程语言一无所知。编辑器须要作的就是与 language server 对话并更新 UI。并且编辑器知道如何作到这一点后,就能够遵循相同的过程,与任何带有 language server 的语言所编写的代码进行交互。
若是你以为以前的 M + N 图有点眼熟,那多是由于 LLVM 也采用了一样的方法。
LLVM 的核心是中间表示(intermediate representation,IR)。LLVM 所支持的语言使用 编译器前端(compiler frontend) 生成 IR,再使用 编译器后端(compiler backend) 将 IR 生成所支持平台的机器码。
若是你想了解 Swift 代码编译的更多细节,请查看 咱们关于 SwiftSyntax 的文章。
Clang 是 C 语言的 LLVM 编译器前端。Swift 与 Objective-C 的互操做性(inter-operability)就是靠它实现的。在最近的 5.0.0 版本中,Clang 添加了一个名为 Clangd 的新工具,它是 LLVM 对 Language Server Protocol 的实现。
2018 年 4 月,苹果公司向 LLVM 邮件组宣布,将把开发的重心从 libclang 转向 Clangd,以其做为建立交互工具的主要方式。
如今你可能会想,“那又怎样?” 苹果公司是 LLVM 项目最重要的支持者之一,该项目创始人 Chris Lattner 已经在苹果公司工做了十多年。苹果公司决定从不透明的 Clang 工具切换到另外一个,彷佛是一个实现细节了(能够这么说)。
这个官宣颇有趣的一点是,Clangd 彷佛彻底是在苹果之外开发的,谷歌和其余公司也作出了重大贡献。这个官宣标志着将来工具开发方向的重大转变 —— 六个月后 Swift.org 论坛将证明这一点。
根据苹果公司 10 月份发布的 LSP 公告,咱们预计在将来几周内(撰写本文时,最先 11 月中旬)将看到该项目的首批代码。
要感觉这些发展的所有影响还须要一些时间,但请相信我:你的耐心是值得的。我相信如下是 LSP 在将来几个月和几年将会发生的一些事情。
虽然 Swift 主要用于 APP 开发,但它从一开始就被设计成一种功能强大的通用编程语言。在 Swift for TensorFlow、 SwiftNIO 和其余项目中,咱们正开始看到 Swift 承诺的在 App Store 以外的使用。
到目前为止,阻碍 Swift 被主流采用的最大因素之一是它对 Xcode 的依赖。
人们会有不少质疑,当有那么多优秀的、门槛低不少的替代方案可选的状况下,为何还要让 Web 开发者或机器学习工程师仅仅为了尝试 Swift 而去下载 Xcode?支持 Language Server Protocol 可让苹果生态圈之外的人更容易地使用他们熟悉工具去感觉 Swift。
支持 LSP 不只仅是让 Swift 在其余编辑器中运行地更好,Xcode 也将受益不浅。
看看苹果 Swift 项目负责人 Ted Kremenek 的 这篇论坛帖子:
@akyrtzi 所描述的 LSP 服务将比今天的 SourceKit 更强大。
LSP 对 Xcode 团队来讲是一个机遇,让他们使用一种新的方法实现 Swift 集成,并能够将其应用在语言和工具自 1.0 版本发布以来四年中的全部改进上。
LSP 的好处并不限于 Swift 和 Objective-C,Argyrios 在那个帖子的另外一个留言中指出:
Xcode 使用咱们新的 LSP 服务,这意味着它也可使用其余 LSP 服务,咱们对此很感兴趣,不过目前暂无具体计划。
目前的工做重点是改进 Swift。可是,一旦实现了这一点,就应该能相对简单地将这些优化转移到支持 LSP 的其余语言中。
软件的架构反映了建立它的组织的结构和价值。在某种程度上,反之亦然。
经过让 Xcode 支持开放的 Language Server Protocol 标准,苹果正在履行其在苹果生态系统以外的平台上实现 Swift 成功的承诺。我认为这是可行的:工具(或缺乏工具)一般是技术得到人心的关键决定因素。但或许更重要的是,我认为这一决定代表,公司内部(至少是一小部分)对合做和透明度的意愿有所加强。
本文由 SwiftGG 翻译组翻译,已经得到做者翻译受权,最新文章请访问 swift.gg。