API 概览
插件可用的所有 API 模块与插件类型可用性。
插件通过 self 访问以下 API 模块。每个模块的可用性取决于插件类型(Ui / Service / Data)以及 plugin.toml 中声明的权限。
通用模块(所有插件类型)
| 模块 | 说明 | Ui | Service | Data |
|---|---|---|---|---|
self.path | 插件/数据/缓存/临时目录路径 | ✓ | ✓ | ✓ |
self.settings | IDE 设置读写 | ✓ | ✓ | ✓ |
self.message | 消息通知 | ✓ | ✓ | ✓ |
self.clipboard | 剪贴板 | ✓ | ✓ | ✓ |
self.dialog | 文件夹选择对话框 | ✓ | ✓ | ✓ |
self.resources | 插件资源(PluginResource) | ✓ | ✓ | ✓ |
self.events | 事件总线订阅 | ✓ | ✓ | ✓ |
self.commands | 命令注册与分派 | ✓ | ✓ | ✓ |
self.configuration | 清单配置读写 | ✓ | ✓ | ✓ |
Ui 与 Service 专用
| 模块 | 说明 | Ui | Service | Data |
|---|---|---|---|---|
self.file | 本地文件操作 | ✓ | ✓ | |
self.board | 设备文件操作 | ✓ | ✓ | |
self.persistence | 键值持久化存储 | ✓ | ✓ | |
self.documents | 文档查询与订阅 | ✓ | ✓ | |
self.runtime | 运行时检查(MicroPython) | ✓ | ✓ | |
self.serial | 串口通信 | ✓ | ✓ | |
self.env | 运行环境(平台/布局/主题模式) | ✓ | ✓ | |
self.theme | 主题贡献 | ✓ | ✓ | ✓ |
self.i18n | 语言包贡献 | ✓ | ✓ | ✓ |
self.stubs | 类型存根贡献 | ✓ | ✓ | ✓ |
Ui 专用
| 模块 | 说明 | Ui | Service | Data |
|---|---|---|---|---|
self.editor | 活动编辑器内容与光标操作 | ✓ | ||
self.views | 原生视图模型与渲染器 facade | ✓ | ||
self.tabs | 将贡献视图打开为标签页 | ✓ |
常用任务速查
不知道用哪个模块时,按"我想做什么"查找:
| 我想… | 用这个 |
|---|---|
| 给用户展示界面 | views(表单/树/表格/日志…)或 components |
| 把视图开成标签页 | tabs |
| 读写工作区文件 | file(本地) / board(设备) |
| 读取/修改当前文档、获取符号 | editor / document |
| 持久化少量键值 | persistence |
| 串口收发数据 | serial |
| 检查设备运行时与变量 | runtime |
| 读 IDE 设置 | settings |
| 声明/读写自己的配置项 | configuration |
| 弹通知 / 选文件夹 / 写剪贴板 | message / dialog / clipboard |
| 获取插件目录与资源 | path / resources |
| 提供命令或菜单动作 | commands |
| 订阅 IDE 事件 | events |
| 了解运行环境 | environment |
| 贡献主题 / 语言包 / 类型存根 | theme / i18n / stubs |
回调模式
所有 API 方法采用统一的回调模式。回调签名固定为 **kwargs:
# 有回调的方法
self.file.get_root_dir(
lambda **cb: print(cb)
)
# 无回调的方法
self.editor.set_text("Hello")一次 API 调用的完整往返如下。插件代码只负责发起调用和处理结果,其余步骤由 SDK 与宿主完成:
回调内容
IDE 的响应分为成功与失败两种,都通过同一个回调送达:
- 成功:响应的
payload.data是映射时,SDK 调用callback(**data)。回调里直接读取各 API 的返回字段,例如path或ports。 - 失败:SDK 调用
callback(error=SdkApiError)。不要用整个回调字典是否为空来判断成功,因为成功响应本身可能没有业务字段;应显式读取error。
def on_connect(error=None, **result):
if error is not None:
print("连接失败:", error.code, error.message)
return
print("连接成功")
self.serial.connect("COM3", callback=on_connect)请求失败(如权限不足)时,callback(error=...) 收到 SdkApiError 实例;未提供回调时,结果会被丢弃,错误只记录到 IDE 诊断面板。
底层有两种发送方式。Bridge.push() 只负责投递,不等待结果;Bridge.push_wait_response() 会按请求 ID 保存回调。宿主响应的 replyTo 指回原请求,SDK 取出并删除对应回调后执行它,因此一个请求只会完成一次。DataPlugin.stop_when_idle() 使用同一份挂起响应计数,所有已登记的请求完成或取消后,事件循环才会退出。
同步与异步
- 回调在 Bridge 事件循环中执行,不在 Flutter UI isolate。不要在其中调用阻塞操作;刷新界面时应更新视图模型。
- 普通 API 的
callback=必须是同步可调用对象。Bridge 会直接调用它,不会 await 返回值。需要启动异步工作时,在同步回调中显式创建任务:
import asyncio
async def process_data(data):
await asyncio.sleep(0.01)
print("data:", data)
def on_data(error=None, **result):
if error is not None:
print("读取失败:", error)
return
asyncio.create_task(process_data(result.get("data")))
self.serial.read(timeout_ms=100, callback=on_data)生命周期钩子、事件订阅处理器和命令处理器有各自的 awaitable 调度逻辑,可以使用普通函数或 async def。不要把这些处理器的规则套用到 API 请求回调。
self.bridge.push()(及所有 API 底层发送)是线程安全的,可从任意后台线程调用;但回调仍会回到事件循环线程执行。
错误体系
SDK 用两套错误机制区分"宿主拒绝的请求"与"本地协议/状态问题"。
SdkApiError(宿主返回的错误响应)
API 请求被宿主拒绝时,回调的 error= 收到 SdkApiError 子类实例。所有实例带 code、message、details 三字段:
| 异常 | 触发场景 |
|---|---|
PermissionDeniedError | 权限不足;required_permission 属性给出缺失权限 |
UnknownCommandError | 当前 IDE 不提供该 SDK 命令(通常因插件类型不支持) |
InvalidPluginContextError | 响应因会话不匹配被拒(跨代或跨会话复用过期句柄) |
SdkApiError(基类) | 其他 IDE 返回的错误(如参数错误) |
def on_result(error=None, **cb):
if isinstance(error, PermissionDeniedError):
print("需要权限:", error.required_permission)
elif error is not None:
print("失败:", error.code, error.message)
self.board.read_file("config.json", callback=on_result)本地异常(SDK 侧直接抛出)
不经过宿主、直接在调用线程抛出的异常:
| 异常 | 触发场景 |
|---|---|
ViewProtocolError | 视图已关闭、快照/补丁超过节点数或字节上限 |
StaleReferenceError | 运行时后端重启后,使用已经失效的 runtime 引用(runtime.*) |
RuntimeUnavailableError | 当前后端不支持运行时检查(capability unavailable) |
PluginContextError | 宿主注入的插件上下文缺失或非法(启动时) |
TransportClosedError | 传输层已关闭(插件已卸载/运行时重启) |
本地异常在请求发送前同步抛出,可用 try/except 直接捕获;宿主错误则以 error= 关键字进入回调。两种路径的边界是:凡是需要宿主回答的,走回调 error=;凡是本地就能判断的,直接抛异常。
documents.symbols() 的修订冲突属于正常业务结果。回调会收到 SymbolResult,其 stale 属性表示请求期间文档已经变化;这一路径不会抛出 StaleRevisionError。收到 stale=True 后,应基于当前文档修订重新请求符号。
API 参考
- view — 视图模型与渲染器
- native_views — 渲染器数据节点与 facade
- components — 通用原生组件
- tab — 标签页
- editor — 活动编辑器操作
- document — 文档查询与订阅
- file — 本地文件操作
- board — 设备文件操作
- persistence — 键值持久化
- serial — 串口通信
- settings — IDE 设置
- configuration — 清单配置
- path — 插件目录路径
- environment — 运行环境
- resources — 插件资源
- clipboard — 剪贴板
- commands — 命令注册/分派
- events — 事件总线
- message — 消息通知
- dialog — 文件夹选择
- runtime — 运行时检查
- theme — 主题贡献
- i18n — 语言包贡献
- stubs — 类型存根贡献