LSP中positionEncoding与范围计算的疑问及编码适配问题
核心现象分析
你遇到的文本乱码(比如package aäbc变成package aäbc),本质是服务端读取Socket数据时用了错误的编码(如Latin-1)解码——LSP规范要求传输的JSON必须用UTF-8编码,所以服务端必须以UTF-8解码收到的字节流,才能正确还原原始文本。
关于Range计数与positionEncodingKind的疑问
1. Range计算必须严格遵循positionEncodingKind的约定
是的,Range中的character值的计数规则完全由协商好的positionEncodingKind决定。
你返回了utf-16作为编码类型,意味着客户端(VS Code)应该以UTF-16代码单元为单位计数字符位置;但你收到的character=10是按**Unicode代码点(可见字符)**计数的结果,这说明客户端和服务端的编码约定没有对齐——要么是VS Code的配置问题,要么是服务端的初始化响应存在疏漏。
举个例子:字符ä是一个Unicode代码点,但在UTF-16中是1个代码单元,在UTF-8中是2个代码单元。如果约定了utf-16,那么package aäbc中b的character值应该是9(package a共8个字符,ä占1个代码单元,所以b的位置是8+1=9);而按代码点计数的话是10,这明显不符合utf-16的约定。
2. positionEncodingKind的核心作用
这个字段是客户端与服务端之间的计数规则协商机制,用来解决多字节字符的位置偏移问题:
utf-16:按UTF-16代码单元计数(VS Code默认支持,也是规范要求必须支持的类型)utf-8:按UTF-8代码单元计数utf-32:按Unicode代码点计数
如果双方不统一这个规则,处理包含多字节字符的文本时,Range的起始/结束位置会完全错位,导致跳转、修改等操作失效。
Socket传输编码的调整问题
LSP规范强制要求传输的JSON数据必须使用UTF-8编码,所以你不能也不需要调整为其他格式。
你通过Wireshark看到的UTF-8编码是符合规范的,之前的乱码问题是服务端解码环节的错误——只要服务端以UTF-8解码Socket收到的字节流,就能正确还原ä、Ö等特殊字符。
内容的提问来源于stack exchange,提问作者Matt

