Skip to main content

BLOGE 0.9.8-RC1 在线版 · 事实校验 2026-09-15 · English

第 9 章 —— 工具链工作流

承诺: 读完本章后,你将理解 BLOGE 工具链的 TypeScript 编写路径与 Java 执行路径如何协同,并且知道怎样为 .bloge 文件建立高效编写循环,在代码审查和上线前捕获错误。


学习目标

  1. 理解 两条实现路径:TypeScript bloge-lang 服务 LSP/Studio 编写,Java bloge-dslbloge-lint 服务 runtime/CI。
  2. 了解 诊断信息如何流转:从词法分析器、解析器、编译器和 lint 规则,经过 LSP,最终变成编辑器中的红色波浪线。
  3. 使用 保存时格式化 通过 DSL 代码生成器保持 .bloge 文件的一致性。
  4. 在 CI 中运行 bloge-lint CLI,并理解它的 Java 规则集与编辑器诊断有重叠但不完全相同。
  5. 追踪 operator-metadata.json 如何从 bloge-maven-plugin 进入 BLOGE Studio 的 operator 面板,再用分屏视图在 DSL 文本和画布之间往返编辑。

前置条件

源示例

文件展示内容
bloge-lang/README.mdTypeScript 编写核心:词法分析器、解析器、编译器、代码生成器、schema
bloge-lsp/README.mdLSP 服务器能力与架构
bloge-lsp/src/server.tsLSP 服务器入口 —— 能力注册
bloge-lsp/src/document-manager.ts五阶段分析流水线(lex → parse → compile → lint → index)
bloge-lsp/src/features/hover.ts关键字、内置函数、节点、schema 和持续时间的悬停文档
bloge-lsp/src/features/completion.ts上下文感知的自动补全
bloge-lsp/src/features/formatting.ts通过 DslCodeGenerator 实现的整文档格式化
bloge-lsp/src/lint/lint-rule.tsLintRule 接口和 LintRunner
bloge-vscode/src/extension.tsVS Code 扩展入口 —— LSP 客户端接线
bloge-vscode/syntaxes/bloge.tmLanguage.json用于语法高亮的 TextMate 语法
bloge-intellij/README.mdIntelliJ 插件 —— 双模式架构(PSI + 可选 LSP 叠加层)
bloge-studio/README.md可视化 DAG 编辑器 —— React 19 + React Flow
bloge-studio/public/operator-metadata.json内置 operator 目录(名称、描述、I/O schema)
bloge-maven-plugin/README.md@BlogeOperator 类生成 operator-metadata.json 的 Maven 插件
bloge-lint/README.mdJava CLI linter —— 规则、.blogerc.json 配置、退出码
ticket-routing.bloge本章通篇使用的示例
missing-timeout.bloge被 lint 捕获的反模式

为什么这很重要

你可以在纯文本编辑器中编写语法正确的 .bloge 文件。但没有工具链的话:

  • 节点 ID 中的拼写错误 要到 graph 引擎启动时才会被发现。
  • 未使用的节点缺失的 timeout 会在审查中被忽略。
  • 格式漂移 使 PR 充满噪音,掩盖了真正的变更。
  • Operator schema 不匹配(Java 代码和 DSL 之间的不一致)在运行时 ClassCastException 之前都是不可见的。

BLOGE 工具链的设计原则是 最快的反馈循环也是成本最低的:输入时红色波浪线就会出现,保存时格式自动规范化,CLI linter 作为最终关卡在 CI 中运行。这些界面并不共享一套实现:LSP 与 Studio 走 TypeScript,runtime 解析与 CLI lint 走 Java;conformance fixture 和导出合同负责约束两条路径的一致性。


心智模型

把工具链想象成两条由兼容性证据连接的反馈路径:

Diagram: 09-tooling-workflow figure 1

关键洞察:对齐边界是共享合同,不是共享代码。 bloge-lang 提供 bloge-lsp 与 Studio 使用的 TypeScript parser/compiler;runtime 与 Maven 走 Java bloge-dslbloge-lint 提供 Java CI 规则;IntelliJ Community 保留 PSI/JFlex 路径,并在支持时叠加 LSP。实现可能漂移,因此一致性需要验证,不能靠假设。


第一个可运行的示例

在安装了 bloge-vscode 扩展的 VS Code 中打开 ticket-routing.bloge 示例。你应该立即看到:

  1. 语法高亮 —— graphnodebranchdepends_on 等关键字被着色;文档注释(///)获得文档注释作用域;像 FetchCustomerOperator 这样的 operator 引用被高亮为类型。

  2. 诊断信息 —— 如果你故意拼错一个 depends_on 目标(比如把 fetchCustomer 改成 fetchCustmer),保存之前就会出现红色下划线。

  3. 悬停 —— 将鼠标悬停在 timeout 上,你会看到:"Sets the maximum execution time for a node."。悬停在 3s 上,你会看到:"Duration: 3s = 3000ms"。悬停在 analyzeSentiment 上,你会看到它的 operator 引用、文档注释、依赖和 timeout。

  4. 补全 —— 在 input { } 块内,输入 =,LSP 会建议 ctx、所有节点 ID 以及 concatsizecoalesce 等内置函数。

  5. 格式化 —— 触发"格式化文档",整个文件会通过 DslCodeGenerator.generate(ast) 重新输出,规范化缩进和空格。

以上五个功能都由 document-manager.ts 中定义的单一流水线驱动:

// Phase 1: Lexing → tokens
// Phase 2: Parsing → AST (GraphDef)
// Phase 3: Compile → CompiledGraph + diagnostics
// Phase 4: Lint → LintRunner.run(ast, compiled)
// Phase 5: Index → buildSymbolIndex(ast, uri, text)

这条五阶段流水线在 每次按键时 运行(通过 server.ts 中的 documents.onDidChangeContent),缓存的 ParseState 会被 hover、completion、definition、references 和 rename 处理器复用。在这五个阶段之后,DocumentManager 还会刷新 import graph 的簿记信息,以保持跨文件特性同步。


跟着一个 PR 走完反馈闭环

工具链的价值,在于缩短“做出编辑”到“得到可评审事实”的距离。设想一个 PR 删除了 missing-timeout.bloge 中外部调用的 timeout。真正有用的故事不是 参观编辑器功能,而是让一个缺陷连续经过四个反馈面。

图:编辑、诊断、lint、测试、评审闭环

一个缺陷使用一个稳定身份

反馈面读者看到什么必须交接什么
编辑器node 位置上的行内诊断ruleId=missing-timeout 与源码位置
CLI lint可复现的非零结果与 CI 相同的 rule id 和 severity
Scenario 测试代表性 Case 的运行行为Case verdict 加 node/effect 证据
PR 评审为什么这个编辑安全诊断已消失,聚焦测试已通过

自动补全能帮你写语法,但不能闭合这个循环。团队真正共享的合同,是稳定的 诊断身份,以及另一名开发者可以重新执行的命令。

先诊断,再决定是否运行全部测试

最短的有效序列是:

EDIT 一处声明
→ 在源码位置 DIAGNOSE
→ 使用与 CI 相同的规则集执行 LINT
→ 运行覆盖变更路径的最小 Scenario
→ 把两类结果一起交给 REVIEW

如果 lint 仍失败,就回到声明;此时运行完整集成套件只会增加噪音。如果 lint 已通过但 Scenario 失败,应检查运行证据;修改 lint 配置修不好业务行为。 只有两个聚焦信号都通过,才值得运行更大范围构建。

这里的声明边界很清楚:lint 证明声明式编写规则,Scenario 证明 fixture 条件 下的行为,任何一项单独成立都不能证明生产正确性。


拆解分析

1 — 共享语言核心:bloge-lang

bloge-lang 是一个纯 TypeScript 库,零依赖。它导出:

  • Lexer —— 手写的扫描器,从 .bloge 源码产生 token。
  • Parser —— 递归下降解析器,带有优先级爬升的表达式解析。处理 import、graph 级别的 input/output schema、signal_schemaoneOf(...)、联合类型、?. 安全导航等。
  • compile(ast, options?) —— 前端语义分析:依赖解析、环检测、schema 校验、联合类型收窄、分支穷尽性检查。当提供了 CompileOptions.importResolver 时,import 会被递归解析。
  • DslCodeGenerator.generate(ast) —— AST 到源码的格式化器。LSP 的格式化功能和 Studio 的导出都使用同一条代码路径。

三行代码即可使用:

import { Lexer, Parser, compile, DslCodeGenerator } from 'bloge-lang';

const tokens = new Lexer(source).tokenize();
const ast = new Parser(tokens).parse();
const result = compile(ast);
// result.diagnostics → 错误、警告
// DslCodeGenerator.generate(ast) → 格式化后的源码

2 — LSP:bloge-lsp

bloge-lspbloge-lang 包装在一个通过 stdio 通信的 Language Server Protocol 服务器中。 server.ts 入口注册了以下能力:

能力处理器文件功能
Diagnosticsdocument-manager.ts来自 lexer + parser + compiler + lint 的实时 error/warning/info
Completionfeatures/completion.ts上下文感知:关键字、节点 ID、schema 类型、内置函数、oneOf(...) 和代码片段模板
Hoverfeatures/hover.ts关键字文档、约 70 个内置函数、node/schema/transform 声明、持续时间
Go to Definitionfeatures/definition.ts基于符号索引的跳转到声明的 nameRange;通过 resolveSymbolCrossFile 支持跨文件
Find Referencesfeatures/references.ts节点/schema/transform 的所有引用,包括传递 importer
Renamefeatures/rename.ts重命名声明 + 所有引用;传播到传递 importer;冲突检查
Formattingfeatures/formatting.ts通过 DslCodeGenerator.generate(ast) 实现整文档格式化
Code Actionsfeatures/code-actions.tsmissing-timeoutmissing-doc-commentunused-nodeno-duplicate-node-id 的快速修复;以及 Source Fix All 批量安全修复
Semantic Tokensfeatures/semantic-tokens.ts全文档语义高亮:graph 名称、operator 引用、节点引用、路径段、字面量、关键字——用 AST 感知的 token 类细化 TextMate 作用域

Import 解析file:// 文档是自动的 —— DocumentManager 接入了一个基于文件的 ImportResolver,相对于打开的文件解析路径,并在需要时追加 .bloge 后缀。被导入文件中的错误会作为诊断信息显示在导入文件中。

3 — Lint 规则

BLOGE lint 采用三层结构。知道一条规则属于哪一层,就知道它在哪里运行、 能看到什么上下文,以及增加新规则时要重建哪个工件。

在哪里运行看到什么例子
Core(15 条)bloge-lint CLI + LSP(翻译成 TS)单个 .bloge 文件解析并编译后的 ASTno-duplicate-node-idno-duplicate-schema-nameunused-nodemissing-timeoutexcessive-fan-outmissing-doc-commentno-cycleno-unresolved-dependencyno-unresolved-branch-targetmax-script-nodesscript-timeout-requiredscript-line-limitloop-exit-completenesscron-expression-validdeadline-in-past
编译器驱动(3 条)编译器自身符号解析和类型检查后的整图 IRschema-validation-strictness-mismatchdynamic-subgraph-output-untypedambiguous-timer
扩展(目前 2 条,可通过 SPI 扩展)对应 *-ext JAR 在 classpath 上时被发现扩展自身的 DSL 表面session-backward-transition-guard(来自 bloge-session-ext)、state-machine-structure(来自 bloge-state-ext

Core 规则 —— LSP 子集

LSP 内置六条交互式规则 (bloge-lsp/src/lint/rules/):

规则 ID严重级别捕获内容
no-duplicate-node-idError节点 ID 被声明了多次
no-duplicate-schema-nameErrorSchema 名称被声明了多次
unused-nodeInfo节点从未被下游引用
missing-timeoutInfo节点没有 timeout
excessive-fan-outInfo节点有超过 5 条出边
missing-doc-commentInfo节点缺少 /// 文档注释

Java 端的 CLI linter(bloge-lint)在批量 检查中包含这些核心规则,同时增加上面表里图级和脚本相关的规则,以及扩展 通过 LintExtensionContributor SPI 贡献的规则。

编译器驱动规则

这 3 条规则由编译器发出,不是 rule runner。你在 .blogerc.json关不掉 —— 它们对应编译器生成合法 Graph 时必须做的结构检查。它们 在 LSP 和 CLI 里和普通规则一样,作为诊断浮出来。

扩展规则

bloge-session-extbloge-state-ext 加进项目就同时引入了它们的 lint 贡献。你也可以通过 LintRuleProvider(Java SPI,CLI)和 BLOGE_LSP_EXTRA_RULES(LSP)注册自定义规则。严重级别和规则参数都可在 .blogerc.json 配置:

{
"rules": {
"missing-timeout": "warning",
"missing-doc-comment": "off"
}
}

决策表规则

bloge LSP 和 CLI 都内置了两条专门针对 decision_table 节点的 lint 规则。使用以下实战配方让决策表保持完备性和意图清晰。

规则 ID严重度触发条件
decision-table/missing-otherwiseWARNINGfirstuniqueany 表没有 otherwise 子句
decision-table/collect-otherwiseINFOcollect 表存在 otherwise 子句(总是追加——可能并非有意为之)

配方 1 —— 通过添加 otherwise 消除 decision-table/missing-otherwise

// [WARN] decision-table/missing-otherwise
decision_table credit_tier(score = ctx.score) hit=first -> String {
rule (score: score >= 750) -> "platinum"
rule (score: 680 <= score < 750) -> "gold"
// 没有 otherwise —— score < 680 时会发生什么?
}

// ✅ 修复后
decision_table credit_tier(score = ctx.score) hit=first -> String {
rule (score: score >= 750) -> "platinum"
rule (score: 680 <= score < 750) -> "gold"
otherwise -> "rejected"
}

配方 2 —— 若 decision-table/collect-otherwise 属于有意为之,显式确认:

// [INFO] decision-table/collect-otherwise
// "baseline" 在每次运行时都会被追加,即使其他规则也命中了。
decision_table discounts(score = ctx.score) hit=collect -> String {
rule (score: score >= 700) -> "loyalty"
otherwise -> "baseline" // 无条件追加——这是有意为之吗?
}

// ✅ 若有意为之,通过 .blogerc.json 覆盖来抑制:
// { "rules": { "decision-table/collect-otherwise": "off" } }
// 若并非有意为之,删除 otherwise 子句。

完整的编译期与运行时错误码列表,请见 附录 F —— 决策表

4 — 编辑器扩展

VS Codebloge-vscode):

  • syntaxes/bloge.tmLanguage.json 处的 TextMate 语法为关键字、文档注释、字符串、操作符、类型和内置函数提供语法高亮作用域。
  • language-configuration.json 处的语言配置提供括号匹配、自动闭合对、注释切换(///* */)和代码块折叠。
  • 扩展入口(extension.ts)将 bloge-lsp 作为子进程通过 stdio 启动,并将其接线为 bloge 语言 ID 的 LSP 客户端。

IntelliJ IDEAbloge-intellij):

  • Community 版 —— 纯 PSI 模式:手写的 JFlex 词法分析器、轻量级 PsiBuilder 解析器、ExternalAnnotator 委托给 bloge-dsl Parser 和 bloge-lint LintRunner、结构视图、代码折叠、语义高亮。无需外部进程。
  • Ultimate / 商业版 —— 可选 LSP 叠加层:BlogeLspServerSupportProvider 启动捆绑的 bloge-lsp Node 服务器;重叠的 PSI 提供者(diagnostics、completion、formatting)退让以避免重复结果。需要 PATH 上有 Node.js 或设置 BLOGE_NODE_PATH

5 — BLOGE Studio

BLOGE Studio 是一个基于浏览器的可视化 DAG 编辑器,使用 React 19 + React Flow 12 构建。它以本地 file: 依赖的方式使用 bloge-lang,复用相同的解析器、编译器和代码生成器。

与你的编写工作流相关的关键功能:

  • 三种视图模式:Visual(仅画布)、Code(仅 Monaco 编辑器)、Split(画布 + 编辑器并排)。Zustand store 在它们之间同步。
  • Operator 面板:从 public/operator-metadata.json 加载。Operator 按层级(基础设施 / 能力 / 领域)标记,支持搜索。拖到画布上即可创建节点。
  • 诊断面板DiagnosticsPanel.tsx —— 显示来自编译器和 lint 规则的 error、warning 和 info。点击一条诊断信息可以在画布上选中对应的节点。
  • 撤销/重做:基于 DSL 快照的历史记录(最多 50 步)。
  • 导出:校验 → 运行代码生成器 → 下载 .bloge 文件。

6 — Operator 元数据流水线

你的 Java operator 代码与可视化工具之间的桥梁是 bloge-maven-plugin

Diagram: 09-tooling-workflow figure 2

该插件在 process-classes 阶段扫描带有 @BlogeOperator 注解的类,反射 Operator<I,O> 的泛型参数,对每个类型调用 SchemaIntrospector.introspect()(支持 Record 和 POJO),并写入一个 JSON 文件。Studio 加载此文件以填充 operator 面板,并为字段补全提供 I/O schema 信息。


内嵌运维控制台 —— /bloge-console

Studio 适合用来编排图。生产环境需要的是另一种视角:"现在哪些 execution 在跑、下一个 timer 什么时候触发、哪个 operator 在抛错。"这个视角就是 /bloge-console —— 一个随 bloge-spring-web 一起发布的小型只读 运维 UI,挂在配置的 base path 上。

spring:
bloge:
console:
enabled: true
base-path: /bloge-console # 默认
require-role: BLOGE_OPS # Spring Security 角色门禁

它展示什么:

  • Executions —— 运行中 / 等待中 / 已完成 / 已失败;点进去看单次 run 的审计日志。
  • Timers —— 当前已 arm 的持久化 timer 及下次触发时间;支持手动 fire now(受 require-role 限制)。
  • Leases —— 当前持有者及剩余 TTL。
  • Schema —— Flyway 的 currentVersion、pending/applied migrations,以及 UP_TO_DATEPENDINGFAILED 状态。
  • Operator registry —— 所有注册的 operator、所在模块,以及 @BlogeOperator 元数据,便于快速发现。

控制台设计上是观测用途。它不让你编辑图(那是 Studio 的事),也不让 你改写 checkpoint(那要走迁移)。"fire timer" 和 "release lease" 是显式的 运维恢复工具,每个动作都以调用者主体写入审计日志。

小测验: 什么时候用 /bloge-console,什么时候用 Studio?提示: Studio 写图,控制台读运行时。


常见陷阱

❌ 假设编辑器和 CI 检查的是相同的规则

LSP 的 lint 规则(TypeScript,在 bloge-lsp 中)和 CLI 的 lint 规则(Java,在 bloge-lint 中)是 两套独立的实现,规则集有重叠但并不完全相同。LSP 有 unused-nodeexcessive-fan-out;CLI 额外覆盖了 no-unresolved-dependencyno-unresolved-branch-targetno-cycle 以及若干脚本规则。如果你只依赖编辑器中的绿色波浪线,CI 仍然可能在 LSP 没有检查的规则上失败。

# 推送前在本地运行 Java linter:
java -jar bloge-lint.jar check src/main/resources/bloge/

# 或者在构建中配置:
# .blogerc.json 控制编辑器和 CLI 使用时的严重级别覆盖。

最佳实践:将 bloge-lint check 作为 pre-commit hook 或 CI 步骤运行,以确保在合并前应用完整的规则集。


引导式重写

missing-timeout.bloge 反模式文件,使用工具链来修复它:

  1. 在 VS Code 中打开(需要安装 bloge-vscode 扩展)。你应该在 loadReport 上看到一条来自 missing-timeout lint 规则的 info 诊断。

  2. 悬停loadReport 上,确认悬停弹窗中没有列出 timeout。

  3. 添加 timeout

    node loadReport : LoadReportOperator {
    input {
    reportId = ctx.reportId
    }
    timeout = 5s
    }
  4. 格式化文档(VS Code 中按 Shift+Alt+F)。DslCodeGenerator 会规范化缩进。

  5. loadReport 上方添加 /// 文档注释。确认 missing-doc-comment 诊断消失。

  6. 对该文件运行 CLI linter

    java -jar bloge-lint.jar check src/main/resources/bloge/antipatterns/missing-timeout.bloge

    添加了 timeout 和文档注释后,输出应报告零个错误。

  7. 在 BLOGE Studio 中打开同一文件(在 bloge-studio/ 中运行 npm run dev,然后使用工具栏中的"Open")。切换到 Split 视图,观察画布和 DSL 代码同步。检查底部的诊断面板 —— 应该是空的。


思维检查

  1. LSP 的格式化功能实际委托给了哪个模块? bloge-lang 中的 DslCodeGenerator。参见 formatting.ts —— 它调用的是 DslCodeGenerator.generate(state.ast)。)

  2. LSP 是如何检测到 depends_on 目标拼写错误的? bloge-lang 中的 compile(ast) 运行依赖解析。无法解析的依赖会产生一个 error 级别的诊断信息,DocumentManager 将其转换为 LSP DiagnosticSeverity.Error。)

  3. 在 IntelliJ 插件中,当 IDE 是 Community 版且没有安装 Node.js 时会怎样? (插件以纯 PSI 模式运行 —— 所有功能由内置的 JFlex 词法分析器、PsiBuilder 解析器和 ExternalAnnotator 提供。LSP 叠加层不会激活,因为 com.intellij.modules.lsp 不存在。)

  4. BLOGE Studio 是如何知道在面板中显示哪些 operator 的? (它在启动时加载 public/operator-metadata.json。该文件可以由 bloge-maven-pluginexport-metadata goal 生成,也可以手动编写。)

  5. 能否在 CLI 中禁用某条 lint 规则?如何操作? (可以 —— 创建一个 .blogerc.json 文件,包含 rules map。将规则 ID 设为 "off"。例如:{ "rules": { "missing-doc-comment": "off" } }。参见 LintConfig.java。)


实验

  1. 编辑器设置:安装 bloge-vscode 扩展(或在 bloge-intellij/ 中运行 ./gradlew runIde 启动 IntelliJ 插件沙箱)。打开 ticket-routing.bloge。 验证:

    • 语法高亮覆盖了所有关键字和文档注释。
    • 悬停在 analyzeSentiment 上会显示其 operator、描述、依赖和 timeout。
    • depends_on 列表中 Ctrl+点击 fetchCustomer 可以跳转到节点声明。
    • 重命名 classifyPriority 会更新分支条件和所有 depends_on 引用。
  2. 故意破坏一个 graph:在 ticket-routing.bloge 中,将 classifyPriority 上的 depends_on = [analyzeSentiment] 改为 depends_on = [nonExistentNode]。观察出现的诊断信息。然后对该文件运行 bloge-lint check,对比 CLI 输出和编辑器波浪线。

  3. Operator 元数据往返:如果你有一个包含 @BlogeOperator 类的 Maven 项目,运行 mvn bloge:export-metadata,将生成的 operator-metadata.json 复制到 bloge-studio/public/ 中。启动 Studio 并确认你的 operator 出现在面板中,且 I/O schema 正确。

  4. Studio 分屏视图:在 BLOGE Studio 中打开 ticket-routing.bloge。 切换到 Split 视图。在代码编辑器中添加一个新节点,观察它出现在画布上。删除它,然后使用撤销(Ctrl+Z)恢复。


桥接:从工具链到验证门禁

编辑器 diagnostics 和 bloge-lint 可以缩短编写反馈,却不会执行经过批准的业务 Scenario。通用 customer module 进入 0.9.8-RC1 验证路径时,应在同一次 Maven 调用中编译 bootstrap,再让 Preview goal 读取 .blogeverify.yaml

mvn test-compile \
com.leanowtech.bloge:bloge-maven-plugin:0.9.8-RC1:verify

生成的 artifact 仍需 source binding,并把 receipt 保存在可变目录之外。本书贷款 starter 在 RC1 中会因 com.leanowtech.bloge.starter.* 类加载边界 fail closed,当前请运行其 JUnit Scenario 测试;不要把 TEST_CLASSPATH_UNAVAILABLE 写成业务失败。第 32 章——变化归因、Maven 与发布决策会解释源码安装、已知限制、命令阶梯和 claim 边界。


实验验收卡

  • 预期与观察: missing-timeout 经 edit、diagnose、lint、Scenario 和 review 形成闭环。
  • 失败与恢复: 删除 timeout 让门禁失败;恢复后重跑最小检查集。
  • 证明边界: 证明工具链阻止已声明缺陷,不证明能发现未编码规则。
  • 练习合同: 一个 PR;只引入或修复一项缺陷;交付诊断、测试、审查记录;三者指向同一规则即停止。

回顾

  • bloge-lang 是 LSP 与 Studio 使用的 TypeScript 编写核心,不是 Java runtime parser。
  • bloge-dsl 是 Java runtime/Maven 解析路径;conformance fixture 与导出合同构成两套实现的兼容性边界。
  • bloge-lspbloge-lang 包装在 LSP 服务器中,通过 stdio 提供 diagnostics、completion、hover、go-to-definition、find references、rename 和 formatting。
  • bloge-vscode 提供 TextMate 语法高亮和语言配置,然后将所有智能功能委托给 bloge-lsp
  • bloge-intellij 在 Community 版以纯 PSI 模式运行,在 Ultimate/商业版上添加可选的 LSP 叠加层。
  • BLOGE Studio 是基于浏览器的可视化编辑器,具有三向视图(visual / code / split)、诊断面板和由 operator-metadata.json 驱动的 operator 面板。
  • bloge-maven-plugin 通过从 @BlogeOperator 注解生成 operator-metadata.json,在 Java operator 代码和可视化工具之间架起桥梁。
  • bloge-lint(Java CLI)在 CI 中运行同类型的 lint 规则;其规则严重级别可通过 .blogerc.json 配置。
  • LSP 和 CLI 的 lint 规则集 有重叠但并不完全相同 —— 始终在 CI 中运行 CLI linter 作为最终关卡。

下一步

第 10 章——用子图复用中,你会继续使用这条反馈循环,把可复用 graph 行为放进明确的父子合同。


参考链接

Coding Agent: Open the versioned task guide.