VSCode插件快餐教程第8讲:LSP文本同步完整实现详解
通过LSP协议实现文本同步,监听文件打开与修改事件,借助TextDocument对象获取URI、版本号、语言ID等属性。支持增量模式仅传输变化部分,全量模式每次传送完整内容,可根据需求灵活选择同步方式。
vscode插件快餐教程(8) - LSP文本同步
从这一节开始,我们来聊一聊如何通过LSP协议做文本同步。说白了,就是让语言服务器知道编辑器里文件内容的变化——打开、修改、关闭这些操作,都需要实时同步过去。
文件打开
先从最简单的入手:监听文件打开事件。这背后的LSP协议里,对应的参数是DidChangeTextDocumentParams结构。先看一张协议结构的截图:

微软的SDK已经在这个协议基础上做了封装,接口更友好。我们来看封装后的API:

当前,TextDocument提供了4个属性:
uri: 文件的URIversion: 文件的版本号languageId: 编程语言lineCount: 有多少行
另外还有3个函数:getText()获取全文,positionAt和offsetAt用于Position和offset之间的转换。
光说不练假把式,直接看代码示例:
documents.onDidOpen((event: TextDocumentChangeEvent) => {
logger.debug(`on open:${event.document.uri}`);
logger.debug(`file version:${event.document.version}`);
logger.debug(`file content:${event.document.getText()}`);
logger.debug(`language id:${event.document.languageId}`);
logger.debug(`line count:${event.document.lineCount}`);
});
跑起来的效果呢?给大家贴一段真实日志:
[2019-06-04T18:11:31.999] [DEBUG] lsp_demo - on open:file:///Users/ziyingliuziying/test.vb
[2019-06-04T18:11:31.999] [DEBUG] lsp_demo - file version:1
[2019-06-04T18:11:31.999] [DEBUG] lsp_demo - file content:dim a as integer;TextView1Ja vascriptButton3Test2
[2019-06-04T18:11:31.999] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:11:32.000] [DEBUG] lsp_demo - line count:6
监听文件变化
监听文件变化与监听打开文件,写法几乎一模一样。代码长这样:
documents.onDidChangeContent((e: TextDocumentChangeEvent) => {
logger.debug('document change received.');
logger.debug(`document version:${e.document.version}`);
logger.debug(`text:${e.document.getText()}`);
logger.debug(`language id:${e.document.languageId}`);
logger.debug(`line count:${e.document.lineCount}`);
});
看看运行时日志,能清楚看到每次修改后版本号递增、内容变化:
[2019-06-04T18:30:34.329] [DEBUG] lsp_demo - document change received.
[2019-06-04T18:30:34.329] [DEBUG] lsp_demo - document version:1
[2019-06-04T18:30:34.329] [DEBUG] lsp_demo - text:dim a as integer;TextView1Ja vascriptButton3Test2
[2019-06-04T18:30:34.329] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:30:34.329] [DEBUG] lsp_demo - line count:6
[2019-06-04T18:30:39.457] [DEBUG] lsp_demo - document change received.
[2019-06-04T18:30:39.457] [DEBUG] lsp_demo - document version:2
[2019-06-04T18:30:39.457] [DEBUG] lsp_demo - text:
[2019-06-04T18:30:39.457] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:30:39.458] [DEBUG] lsp_demo - line count:2
[2019-06-04T18:30:41.576] [DEBUG] lsp_demo - document change received.
[2019-06-04T18:30:41.576] [DEBUG] lsp_demo - document version:3
[2019-06-04T18:30:41.577] [DEBUG] lsp_demo - text:b
[2019-06-04T18:30:41.577] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:30:41.577] [DEBUG] lsp_demo - line count:1
[2019-06-04T18:30:41.949] [DEBUG] lsp_demo - document change received.
[2019-06-04T18:30:41.949] [DEBUG] lsp_demo - document version:4
[2019-06-04T18:30:41.949] [DEBUG] lsp_demo - text:u
[2019-06-04T18:30:41.949] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:30:41.949] [DEBUG] lsp_demo - line count:1
[2019-06-04T18:30:42.447] [DEBUG] lsp_demo - document change received.
[2019-06-04T18:30:42.447] [DEBUG] lsp_demo - document version:5
[2019-06-04T18:30:42.447] [DEBUG] lsp_demo - text:Button5
[2019-06-04T18:30:42.447] [DEBUG] lsp_demo - language id:vb
[2019-06-04T18:30:42.447] [DEBUG] lsp_demo - line count:1
文本监听模式
上面使用的监听方式是增量监听,对应的模式是TextDocumentSyncKind.Incremental。具体初始化代码里这样配置:
connection.onInitialize((params: InitializeParams) => {
return {
capabilities: {
textDocumentSync: {
openClose: true,
change: TextDocumentSyncKind.Incremental
},
completionProvider: {
resolveProvider: true
}
}
};
});
增量模式好理解:每次只把变化了的部分传过去,网络开销小。但如果需要完整状态,也可以改成全量模式。区别只在于把Incremental换成Full:
connection.onInitialize((params: InitializeParams) => {
return {
capabilities: {
textDocumentSync: {
openClose: true,
change: TextDocumentSyncKind.Full
},
completionProvider: {
resolveProvider: true
}
}
};
});
全量模式下,每次变化后都会把整个文件内容原封不动传过来。看日志就清楚了:
[2019-06-04T19:52:12.305] [DEBUG] lsp_demo - document change received.
[2019-06-04T19:52:12.305] [DEBUG] lsp_demo - document version:1
[2019-06-04T19:52:12.305] [DEBUG] lsp_demo - text:dim a as integer;TextView1Ja vascriptButton3Test2Button5
[2019-06-04T19:52:12.305] [DEBUG] lsp_demo - language id:vb
[2019-06-04T19:52:12.305] [DEBUG] lsp_demo - line count:7
[2019-06-04T19:52:19.442] [DEBUG] lsp_demo - document change received.
[2019-06-04T19:52:19.442] [DEBUG] lsp_demo - document version:2
[2019-06-04T19:52:19.442] [DEBUG] lsp_demo - text:dim a as integer;TextView1Ja vascriptButton3Test2Button5T
[2019-06-04T19:52:19.443] [DEBUG] lsp_demo - language id:vb
[2019-06-04T19:52:19.443] [DEBUG] lsp_demo - line count:7
[2019-06-04T19:52:19.443] [DEBUG] lsp_demo - onCompletion
[2019-06-04T19:52:19.787] [DEBUG] lsp_demo - document change received.
[2019-06-04T19:52:19.787] [DEBUG] lsp_demo - document version:5
[2019-06-04T19:52:19.787] [DEBUG] lsp_demo - text:dim a as integer;TextView1Ja vascriptButton3Test2Button5Test
[2019-06-04T19:52:19.787] [DEBUG] lsp_demo - language id:vb
[2019-06-04T19:52:19.787] [DEBUG] lsp_demo - line count:7
[2019-06-04T19:52:19.788] [DEBUG] lsp_demo - onCompletion
[2019-06-04T19:52:21.877] [DEBUG] lsp_demo - document change received.
[2019-06-04T19:52:21.877] [DEBUG] lsp_demo - document version:6
[2019-06-04T19:52:21.877] [DEBUG] lsp_demo - text:dim a as integer;TextView1Ja vascriptButton3Test2Button5Test
[2019-06-04T19:52:21.877] [DEBUG] lsp_demo - language id:vb
[2019-06-04T19:52:21.877] [DEBUG] lsp_demo - line count:8
除了增量和全量,还有一种TextDocumentSyncKind.None模式,选了它就连文本都不同步了——基本用不上,除非你的语言服务器完全不需要文件内容,只靠URI做标记。但大多数场景下,还是增量和全量二选一,至于选哪个,看你服务器对完整内容的依赖程度和网络带宽的考量。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
Claude Code 必知的14个高效工作流,让你的开发效率提升300%
Claude Code 常用工作流 先分享几项核心判断:Claude Code 真正强大的地方,并非仅仅在于它能编写代码——而是它让“编码”这件事本身变得更加高效且可控。你大概率遇到过这类场景:接手一个陌生项目,花了一整天才能理清架构;线上出现报错,翻遍日志也找不到根本原因;想要重构遗留代码,又担心
阿里云通义AIGC平台完全指南:设计师AI生产力革命
一、写在前面:为什么设计师需要关注AIGC? 如果你还在手动一张一张制作海报、反复修改客户口中“感觉不对”的配色方案、为电商详情页准备几十张不同场景的产品图——那么你一定经历过这些痛点: 创意瓶颈:脑海中有画面,但手绘无法呈现 重复劳动:调整尺寸、更换背景、批量生成变体消耗了大量时间精力 成本焦虑:
零基础毕设代码二次开发:3文件定位法及Vue/Java修改对照表
每年一到毕业季,计算机专业的同学总会陷入一个共同的怪圈:从 GitHub 上扒下来一套代码,或者用 AI 生成一个项目,看起来挺完整的,可导师一句“加个筛选条件”或“换个页面颜色”,瞬间就懵了——不敢改,不会改,怕改崩。是不是很熟悉? 一、为什么AI生成的毕设代码你 "不敢改 "? 1 1 毕业生的三大
反向海淘订单系统:状态机与分布式事务实战设计
先分享一个反直觉的结论:反向海淘订单管理的真正挑战,往往不在于业务逻辑本身,而在于状态流转。一个订单的生命周期拉长到跨国运输,中间涉及的环节多、系统多、参与者多,状态稍有错乱就可能引发连锁事故。Taocarts团队在实践中踩了不少坑,最终沉淀下来的这套状态机与分布式事务方案,成功解决了这一复杂难题。
AI并未抢走程序员饭碗而是更新了编程菜单
AI并未大规模替代程序员,而是改变了职业结构。重复性编码岗位需求下降35%至15%,而AIAgent开发等岗位需求激增187%。开发者焦虑从“被替代”转向“跟不上变化”,60%程序员已使用AI辅助编程。人的核心价值转向架构设计、技术决策和审查AI生成代码,AI技能带来16%薪资溢价。
- 热门数据榜
相关攻略
2026-07-09 17:49
2026-07-09 16:48
2026-07-09 16:46
2026-07-09 16:46
2026-07-09 16:46
2026-07-09 16:46
2026-07-09 15:45
2026-07-09 15:45
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

