LikeC4 视图 include/exclude 谓词与通配符(*、_、**)完整指南
【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4
本篇技术指南聚焦 LikeC4 视图(views)中include/exclude谓词的三类通配符语义(*、_、**)与作用域视图(scoped view)的 include 基集行为,结合本仓库 like-c4.langium 文法定义与 FqnRefParser.ts 解析实现,讲清"立即子级 vs 递归后代"的边界、where过滤组合、关系谓词->/<->的邻居扩展规则,以及常见误用。读完你将能精确控制任意层级模型的元素与关系显示,写出可维护、可预期的视图定义。
三种通配符语义:*、_、**
LikeC4 的视图谓词中定义了三种通配符形式:*、_和**,它们的作用范围截然不同。理解三者差异是掌握 LikeC4 视图过滤的第一步。
*— 立即子级与直接包含关系
views { view container-overview { include * } }include *的语义要点:
- 包含作用域元素的直接子级(向下仅一层);
- 包含同一作用域下定义的直接关系(direct relationships defined at the same scope);
- 不包含孙级或更深的后代链条(grandchildren / descendant chains)。
从文法上看,ViewRulePredicate: (isInclude?='include' | 'exclude') exprs=Expressions(见 like-c4.langium)中谓词统一解析为表达式列表;而在解析层,带. *选择器的 Fqn 引用被归一化为selector: 'children'(见 FqnRefParser.ts),这也印证了*只代表"子级"而非"所有后代"。
_— 匿名匹配器(匹配任意元素)
views { view with-predicates { include * where kind is service exclude _ where tag is #deprecated } }_匹配模型中的任意元素(any element in the model);- 通常与
where谓词配合,按 kind、tag 或 metadata 进行筛选; - 典型用法:
exclude _ where tag is #deprecated—— 排除所有打了 deprecated 标签的元素。
在解析实现中,._选择器被映射为selector: 'expanded'(见 FqnRefParser.ts),与*(children)和**(descendants)在语义上有本质区别。
**— 递归下降(所有后代)
views { view full-tree { include ** } }- 递归包含所有后代(孙级、曾孙级……直至叶子);
- 不是
include *的同义形式(后者仅立即子级); - 当你希望在单个视图中呈现完整嵌套层级时使用。
对应源码中,.**选择器被映射为selector: 'descendants'(见 FqnRefParser.ts),并在 fqn-index.ts 的descendants索引中按全限定名(Fqn)查询所有后代节点。
作用域视图(Scoped View)的 include 基集语义
在作用域视图中(view name of parent { ... }),include的基集(base set)有特殊含义:
views { view backend-overview of cloud.backend { include * // 基集:cloud.backend + 其立即子级 include -> cloud.backend // 追加:指向作用域的内向关系 include -> * // 追加:子级出发的外向关系 } }关键事实:
- 作用域视图中的
include *= 作用域父元素 +仅直接子级; *上下文内的孙级不会被包含(需要include **或显式 FQN 包含);->、<->等关系谓词可以进一步扩展出现的邻居元素。
仓库中 issue-912.spec.ts 的测试用例即验证了include b1, b1.*, b2, b2.*这类"父级 + 子级"组合的解析行为,可作为作用域/非作用域视图混合使用的参考。
常见过滤模式
展示容器及其组件
views { view container-details of cloud.backend.api { include * // api(父级)+ 全部组件 include -> api // 追加外部调用方 } }递归展示后代
views { view system-tree of cloud { include ** // cloud 的全部后代(完整树) } }按 kind 过滤
views { view services-only { include * where kind is service include ** where kind is service // 任意层级的全部 service } }按 tag 过滤
views { view critical-view { include * where tag is #critical exclude _ where tag is #deprecated } }按 metadata 过滤(真实仓库示例)
本仓库 metadata-views/views.c4 提供了完整的元数据过滤实战样例,展示了where谓词与metadata组合的多种写法:
views { view metadataProdOnly of metadataExample { title 'Production Only' include * where metadata.environment is "production" } view metadataNotStaging of metadataExample { title 'Exclude Staging' include * exclude * where metadata.environment is "staging" } view metadataHasVersion of metadataExample { title 'Elements with Version' include * where metadata.version } view metadataProdComponents of metadataExample { title 'Prod Components (not databases)' include * where metadata.environment is "production" and kind is not database } view metadataCritical of metadataExample { title 'Critical Components' include * where metadata.critical is true } }这些示例展示了where谓词的表达能力:可比较字符串(is "production")、判断存在性(where metadata.version)、布尔值(is true)、以及用and组合条件并叠加kind is not database这样的否定 kind 过滤。
混合多级通配符的真实用法
cloud-system/views.c4 是一个同时运用*、cloud.*与exclude的典型视图:
views { view cloud of cloud { title "The Cloud System" include *, ui.*, next.*, legacy.* exclude supportUser, ui.supportPanel, next -> legacy ... } }其中ui.*、next.*、legacy.*表示"某元素下的直接子级"(children 选择器),与裸*(当前作用域下直接子级 + 直接关系)形成互补;exclude则同时支持元素 FQN 与关系表达式(next -> legacy),说明 exclude 与 include 共享同一套表达式语法。
关系谓词扩展(Relationship Predicate Expansion)
在作用域视图中,可以通过关系谓词扩展出现的邻居元素:
views { view backend-with-neighbors of cloud.backend { include * // 基集:backend 作用域 + 直接子级 include -> cloud.backend // 追加:来自作用域外部的内向边 } }关键点:这不会改变元素的基集(base set of elements)——它只是包含以可见元素为终点的关系。为了让这些边在视觉上可渲染,拥有入边(incoming edges)的作用域邻居元素也会被一并带入。
总结三种关系谓词的扩展方向:
| 形式 | 含义 | 效果 |
|---|---|---|
include -> element | element 的内向关系 | 显示外部来源 |
include element -> | element 的外向关系 | 显示目标 |
include <-> element | element 的双向关系 | 显示对称依赖 |
通配符**与显式 include 的取舍
使用**(递归)
views { view all-elements { include ** } }- 自动包含全部后代;
- 适用于层级深度未知或会变化的场景。
使用*+ 显式 FQN
views { view two-levels { include * // 第 1 层 include cloud.* // cloud 之下的第 2 层 } }- 更显式,需要事先了解层级结构;
- 适合需要精细粒度控制的场景。
常见错误(Common Mistakes)
| 错误写法 | 正确写法 | 原因 |
|---|---|---|
include **却只想要立即子级 | include * | **是递归的;单层请用* |
| 作用域视图中忘记追加关系过滤 | include *+include -> parent | 不显式包含时关系可能不会自动渲染 |
误以为include *会包含孙级 | 改用include ** | *仅限立即子级 |
总结表
| 形式 | 匹配内容 | 作用域上下文 |
|---|---|---|
* | 直接子级 + 同级关系 | 向下一层 |
_ | 任意元素(配合where过滤) | 按 kind、tag、metadata 匹配 |
** | 递归所有后代 | 任意深度 |
include -> element | element 的内向关系 | 显示外部来源 |
include element -> | element 的外向关系 | 显示目标 |
include <-> element | element 的双向关系 | 显示对称依赖 |
作用域视图中的要点:include *建立的基集 = 作用域父元素 + 立即子级;->与<->关系谓词可以带入渲染这些关系所需的邻居元素。
进阶:全局谓词组复用
当多个视图需要重复使用相同的 include/exclude 规则时,LikeC4 文法还提供了predicateGroup机制(见 like-c4.langium):
predicateGroup name { // 这里可以写任意 ViewRulePredicate }全局谓词组内嵌ViewRulePredicate*,可在视图规则中通过global predicate <name>引用(见 ViewRuleGlobalPredicateRef),把*、**、where过滤等常用组合抽成可复用的谓词单元,减少多视图间的重复代码。这一机制与本指南中的通配符语义完全正交,可与任意谓词组合使用。
【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考