629 lines
14 KiB
Markdown
629 lines
14 KiB
Markdown
|
# VWED LSP代码补全服务接口文档
|
|||
|
|
|||
|
## 概述
|
|||
|
|
|||
|
VWED LSP代码补全服务基于Language Server Protocol(LSP)标准,通过WebSocket协议为前端脚本编辑器提供智能代码补全、函数签名提示、悬停信息等功能。该服务专门针对VWED内置模块和Python语法进行了优化。
|
|||
|
|
|||
|
**基础URL**: `/lsp`
|
|||
|
|
|||
|
**协议**: WebSocket + LSP (Language Server Protocol)
|
|||
|
|
|||
|
**版本**: v1.0
|
|||
|
|
|||
|
**支持的功能**:
|
|||
|
- VWED内置模块智能补全(api、function、event、timer等)
|
|||
|
- Python关键字和内置函数补全
|
|||
|
- 变量和函数名补全
|
|||
|
- 函数签名提示
|
|||
|
- 悬停信息显示
|
|||
|
- 语法验证
|
|||
|
- 实时文档同步
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 1. WebSocket连接
|
|||
|
|
|||
|
### 1.1 建立LSP连接
|
|||
|
|
|||
|
**连接地址**: `ws://localhost:8000/lsp/code-completion/{client_id}`
|
|||
|
|
|||
|
**参数说明**:
|
|||
|
- `client_id`: 客户端唯一标识符,建议使用时间戳+随机字符串
|
|||
|
|
|||
|
**连接示例**:
|
|||
|
```javascript
|
|||
|
const clientId = 'editor-' + Date.now();
|
|||
|
const ws = new WebSocket(`ws://localhost:8000/lsp/code-completion/${clientId}`);
|
|||
|
```
|
|||
|
|
|||
|
### 1.2 连接状态监控
|
|||
|
|
|||
|
连接建立后,客户端可通过以下方式监控连接状态:
|
|||
|
|
|||
|
```javascript
|
|||
|
ws.onopen = () => {
|
|||
|
console.log('LSP服务连接成功');
|
|||
|
// 发送初始化请求
|
|||
|
sendInitialize();
|
|||
|
};
|
|||
|
|
|||
|
ws.onclose = () => {
|
|||
|
console.log('LSP服务连接已断开');
|
|||
|
};
|
|||
|
|
|||
|
ws.onerror = (error) => {
|
|||
|
console.log('LSP服务连接错误:', error);
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 2. LSP协议消息
|
|||
|
|
|||
|
所有LSP消息都遵循JSON-RPC 2.0标准格式:
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 1, // 请求ID(响应类消息必填)
|
|||
|
"method": "方法名", // LSP方法名
|
|||
|
"params": {} // 参数对象
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 2.1 初始化请求
|
|||
|
|
|||
|
客户端连接后必须首先发送初始化请求。
|
|||
|
|
|||
|
**方法**: `initialize`
|
|||
|
|
|||
|
**请求参数**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 1,
|
|||
|
"method": "initialize",
|
|||
|
"params": {
|
|||
|
"clientInfo": {
|
|||
|
"name": "VWED Editor",
|
|||
|
"version": "1.0.0"
|
|||
|
},
|
|||
|
"capabilities": {
|
|||
|
"textDocument": {
|
|||
|
"completion": {
|
|||
|
"dynamicRegistration": false
|
|||
|
},
|
|||
|
"signatureHelp": {
|
|||
|
"dynamicRegistration": false
|
|||
|
},
|
|||
|
"hover": {
|
|||
|
"dynamicRegistration": false
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 1,
|
|||
|
"result": {
|
|||
|
"capabilities": {
|
|||
|
"completionProvider": {
|
|||
|
"triggerCharacters": [".", " "],
|
|||
|
"resolveProvider": false
|
|||
|
},
|
|||
|
"signatureHelpProvider": {
|
|||
|
"triggerCharacters": ["(", ","]
|
|||
|
},
|
|||
|
"hoverProvider": true,
|
|||
|
"textDocumentSync": {
|
|||
|
"openClose": true,
|
|||
|
"change": 2
|
|||
|
}
|
|||
|
},
|
|||
|
"serverInfo": {
|
|||
|
"name": "VWED Python Language Server",
|
|||
|
"version": "1.0.0"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 3. 文档生命周期管理
|
|||
|
|
|||
|
### 3.1 打开文档
|
|||
|
|
|||
|
**方法**: `textDocument/didOpen`
|
|||
|
|
|||
|
**参数说明**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"method": "textDocument/didOpen",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py",
|
|||
|
"languageId": "python",
|
|||
|
"version": 1,
|
|||
|
"text": "def boot():\n VWED."
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 3.2 文档变更
|
|||
|
|
|||
|
**方法**: `textDocument/didChange`
|
|||
|
|
|||
|
**参数说明**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"method": "textDocument/didChange",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py",
|
|||
|
"version": 2
|
|||
|
},
|
|||
|
"contentChanges": [
|
|||
|
{
|
|||
|
"text": "def boot():\n VWED.api."
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 3.3 关闭文档
|
|||
|
|
|||
|
**方法**: `textDocument/didClose`
|
|||
|
|
|||
|
**参数说明**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"method": "textDocument/didClose",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 4. 代码补全功能
|
|||
|
|
|||
|
### 4.1 请求代码补全
|
|||
|
|
|||
|
**方法**: `textDocument/completion`
|
|||
|
|
|||
|
**请求参数**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 2,
|
|||
|
"method": "textDocument/completion",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py"
|
|||
|
},
|
|||
|
"position": {
|
|||
|
"line": 1,
|
|||
|
"character": 10
|
|||
|
},
|
|||
|
"context": {
|
|||
|
"documentText": "def boot():\n VWED."
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 2,
|
|||
|
"result": {
|
|||
|
"isIncomplete": false,
|
|||
|
"items": [
|
|||
|
{
|
|||
|
"label": "api",
|
|||
|
"kind": 9,
|
|||
|
"detail": "VWED.api",
|
|||
|
"documentation": "VWED内置api模块",
|
|||
|
"insertText": "api",
|
|||
|
"sortText": "01_api"
|
|||
|
},
|
|||
|
{
|
|||
|
"label": "log",
|
|||
|
"kind": 9,
|
|||
|
"detail": "VWED.log",
|
|||
|
"documentation": "VWED内置log模块",
|
|||
|
"insertText": "log",
|
|||
|
"sortText": "01_log"
|
|||
|
},
|
|||
|
{
|
|||
|
"label": "register",
|
|||
|
"kind": 2,
|
|||
|
"detail": "(path, method, handler)",
|
|||
|
"documentation": "注册API接口",
|
|||
|
"insertText": "register",
|
|||
|
"sortText": "01_register"
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 4.2 补全项类型说明
|
|||
|
|
|||
|
补全项的`kind`字段使用LSP标准定义:
|
|||
|
|
|||
|
| Kind | 值 | 说明 |
|
|||
|
|------|---|------|
|
|||
|
| Text | 1 | 文本 |
|
|||
|
| Method | 2 | 方法 |
|
|||
|
| Function | 3 | 函数 |
|
|||
|
| Variable | 6 | 变量 |
|
|||
|
| Module | 9 | 模块 |
|
|||
|
| Keyword | 14 | 关键字 |
|
|||
|
|
|||
|
### 4.3 VWED模块补全示例
|
|||
|
|
|||
|
当用户输入`VWED.`时,系统会返回以下模块补全:
|
|||
|
|
|||
|
- `api` - API接口管理模块
|
|||
|
- `function` - 函数注册模块
|
|||
|
- `event` - 事件管理模块
|
|||
|
- `timer` - 定时器模块
|
|||
|
- `log` - 日志记录模块
|
|||
|
- `task` - 任务管理模块
|
|||
|
- `data` - 数据缓存模块
|
|||
|
- `util` - 工具函数模块
|
|||
|
- `device` - 设备控制模块
|
|||
|
|
|||
|
当用户输入`VWED.api.`时,系统会返回api模块的方法补全:
|
|||
|
- `register()` - 注册API接口
|
|||
|
- `unregister()` - 注销API接口
|
|||
|
- `get_registered_apis()` - 获取已注册的API列表
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 5. 函数签名提示
|
|||
|
|
|||
|
### 5.1 请求签名帮助
|
|||
|
|
|||
|
**方法**: `textDocument/signatureHelp`
|
|||
|
|
|||
|
**请求参数**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 3,
|
|||
|
"method": "textDocument/signatureHelp",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py"
|
|||
|
},
|
|||
|
"position": {
|
|||
|
"line": 1,
|
|||
|
"character": 20
|
|||
|
},
|
|||
|
"context": {
|
|||
|
"documentText": "def boot():\n VWED.api.register("
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 3,
|
|||
|
"result": {
|
|||
|
"signatures": [
|
|||
|
{
|
|||
|
"label": "VWED.api.register(path, method, handler)",
|
|||
|
"documentation": "注册API接口\n\npath: API路径\nmethod: HTTP方法\nhandler: 处理函数",
|
|||
|
"parameters": [
|
|||
|
{
|
|||
|
"label": "path",
|
|||
|
"documentation": "API路径字符串"
|
|||
|
},
|
|||
|
{
|
|||
|
"label": "method",
|
|||
|
"documentation": "HTTP方法(GET/POST/PUT/DELETE)"
|
|||
|
},
|
|||
|
{
|
|||
|
"label": "handler",
|
|||
|
"documentation": "处理函数"
|
|||
|
}
|
|||
|
],
|
|||
|
"activeParameter": 0
|
|||
|
}
|
|||
|
],
|
|||
|
"activeSignature": 0,
|
|||
|
"activeParameter": 0
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 6. 悬停信息
|
|||
|
|
|||
|
### 6.1 请求悬停信息
|
|||
|
|
|||
|
**方法**: `textDocument/hover`
|
|||
|
|
|||
|
**请求参数**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 4,
|
|||
|
"method": "textDocument/hover",
|
|||
|
"params": {
|
|||
|
"textDocument": {
|
|||
|
"uri": "file:///path/to/script.py"
|
|||
|
},
|
|||
|
"position": {
|
|||
|
"line": 1,
|
|||
|
"character": 15
|
|||
|
},
|
|||
|
"context": {
|
|||
|
"documentText": "def boot():\n VWED.api.register"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 4,
|
|||
|
"result": {
|
|||
|
"contents": {
|
|||
|
"kind": "markdown",
|
|||
|
"value": "```python\nVWED.api.register(path, method, handler)\n```\n\n注册API接口到VWED动态路由系统"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 7. HTTP管理接口
|
|||
|
|
|||
|
### 7.1 健康检查
|
|||
|
|
|||
|
**接口地址**: `GET /lsp/health`
|
|||
|
|
|||
|
**功能说明**: 检查LSP服务健康状态
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"status": "healthy",
|
|||
|
"service": "VWED LSP Code Completion",
|
|||
|
"active_connections": 2,
|
|||
|
"capabilities": [
|
|||
|
"textDocument/completion",
|
|||
|
"textDocument/signatureHelp",
|
|||
|
"textDocument/hover",
|
|||
|
"textDocument/didOpen",
|
|||
|
"textDocument/didChange",
|
|||
|
"textDocument/didClose"
|
|||
|
]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 7.2 获取活跃客户端
|
|||
|
|
|||
|
**接口地址**: `GET /lsp/clients`
|
|||
|
|
|||
|
**功能说明**: 获取当前连接的LSP客户端列表
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
```json
|
|||
|
{
|
|||
|
"active_clients": [
|
|||
|
{
|
|||
|
"client_id": "editor-1640000000000",
|
|||
|
"initialized": true,
|
|||
|
"document_count": 1,
|
|||
|
"documents": ["file:///test.py"]
|
|||
|
}
|
|||
|
],
|
|||
|
"total_count": 1
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 8. 错误处理
|
|||
|
|
|||
|
### 8.1 LSP错误响应格式
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"jsonrpc": "2.0",
|
|||
|
"id": 1,
|
|||
|
"error": {
|
|||
|
"code": -32603,
|
|||
|
"message": "Internal error: 具体错误信息"
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 8.2 常见错误代码
|
|||
|
|
|||
|
| 错误代码 | 说明 |
|
|||
|
|---------|------|
|
|||
|
| -32700 | Parse error - JSON解析错误 |
|
|||
|
| -32601 | Method not found - 方法未找到 |
|
|||
|
| -32603 | Internal error - 服务器内部错误 |
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 9. 客户端集成示例
|
|||
|
|
|||
|
### 9.1 JavaScript集成示例
|
|||
|
|
|||
|
```javascript
|
|||
|
class VWEDLSPClient {
|
|||
|
constructor(editorElement) {
|
|||
|
this.editor = editorElement;
|
|||
|
this.ws = null;
|
|||
|
this.requestId = 1;
|
|||
|
this.clientId = 'editor-' + Date.now();
|
|||
|
}
|
|||
|
|
|||
|
connect() {
|
|||
|
this.ws = new WebSocket(`ws://localhost:8000/lsp/code-completion/${this.clientId}`);
|
|||
|
|
|||
|
this.ws.onopen = () => {
|
|||
|
this.sendInitialize();
|
|||
|
this.sendDidOpen();
|
|||
|
};
|
|||
|
|
|||
|
this.ws.onmessage = (event) => {
|
|||
|
const message = JSON.parse(event.data);
|
|||
|
this.handleMessage(message);
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
sendInitialize() {
|
|||
|
this.sendMessage({
|
|||
|
jsonrpc: "2.0",
|
|||
|
id: this.requestId++,
|
|||
|
method: "initialize",
|
|||
|
params: {
|
|||
|
clientInfo: { name: "VWED Editor", version: "1.0.0" },
|
|||
|
capabilities: {
|
|||
|
textDocument: {
|
|||
|
completion: { dynamicRegistration: false }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
requestCompletion(position) {
|
|||
|
this.sendMessage({
|
|||
|
jsonrpc: "2.0",
|
|||
|
id: this.requestId++,
|
|||
|
method: "textDocument/completion",
|
|||
|
params: {
|
|||
|
textDocument: { uri: "file:///script.py" },
|
|||
|
position: position,
|
|||
|
context: { documentText: this.editor.value }
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
sendMessage(message) {
|
|||
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|||
|
this.ws.send(JSON.stringify(message));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
handleMessage(message) {
|
|||
|
if (message.method === 'textDocument/completion' && message.result) {
|
|||
|
this.showCompletions(message.result.items);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 9.2 TypeScript接口定义
|
|||
|
|
|||
|
```typescript
|
|||
|
interface LSPPosition {
|
|||
|
line: number;
|
|||
|
character: number;
|
|||
|
}
|
|||
|
|
|||
|
interface LSPCompletionItem {
|
|||
|
label: string;
|
|||
|
kind: number;
|
|||
|
detail?: string;
|
|||
|
documentation?: string;
|
|||
|
insertText?: string;
|
|||
|
sortText?: string;
|
|||
|
}
|
|||
|
|
|||
|
interface LSPCompletionResult {
|
|||
|
isIncomplete: boolean;
|
|||
|
items: LSPCompletionItem[];
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 10. 性能优化建议
|
|||
|
|
|||
|
### 10.1 客户端优化
|
|||
|
|
|||
|
1. **防抖处理**: 对频繁的文档变更事件进行防抖处理
|
|||
|
2. **增量更新**: 使用增量文档更新而非全量更新
|
|||
|
3. **连接复用**: 同一编辑器实例复用WebSocket连接
|
|||
|
4. **缓存补全**: 对补全结果进行适当缓存
|
|||
|
|
|||
|
### 10.2 触发条件
|
|||
|
|
|||
|
建议在以下情况触发代码补全:
|
|||
|
- 用户输入`.`字符
|
|||
|
- 用户按下`Ctrl+Space`
|
|||
|
- 输入标识符字符超过2个
|
|||
|
- 用户停止输入500ms后
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 11. 注意事项
|
|||
|
|
|||
|
1. **连接管理**: 客户端断开时应主动关闭WebSocket连接
|
|||
|
2. **文档同步**: 确保客户端和服务端的文档内容同步
|
|||
|
3. **错误处理**: 妥善处理网络异常和协议错误
|
|||
|
4. **资源清理**: 及时清理不再使用的文档和连接资源
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 附录:VWED内置模块参考
|
|||
|
|
|||
|
### A.1 VWED.api模块
|
|||
|
- `register(path, method, handler)` - 注册API接口
|
|||
|
- `unregister(path, method)` - 注销API接口
|
|||
|
- `get_registered_apis()` - 获取已注册API列表
|
|||
|
|
|||
|
### A.2 VWED.log模块
|
|||
|
- `info(message)` - 记录信息日志
|
|||
|
- `error(message)` - 记录错误日志
|
|||
|
- `debug(message)` - 记录调试日志
|
|||
|
- `warning(message)` - 记录警告日志
|
|||
|
|
|||
|
### A.3 VWED.function模块
|
|||
|
- `register(name, handler)` - 注册函数
|
|||
|
- `unregister(name)` - 注销函数
|
|||
|
- `call(name, args)` - 调用已注册函数
|
|||
|
|
|||
|
### A.4 VWED.timer模块
|
|||
|
- `create(interval, callback)` - 创建定时器
|
|||
|
- `destroy(timer_id)` - 销毁定时器
|
|||
|
- `get_active_timers()` - 获取活跃定时器列表
|
|||
|
|
|||
|
### A.5 VWED.event模块
|
|||
|
- `listen(event_name, handler)` - 监听事件
|
|||
|
- `emit(event_name, data)` - 触发事件
|
|||
|
- `unlisten(event_name, handler)` - 取消监听
|
|||
|
|
|||
|
更多模块详情请参考"在线脚本编辑接口文档"。
|