LikeC4 视图 include/exclude 谓词与通配符(`*`、`_`、`**`)完整指南
2026/9/18 5:06:17 网站建设 项目流程

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 -> elementelement 的内向关系显示外部来源
include element ->element 的外向关系显示目标
include <-> elementelement 的双向关系显示对称依赖

通配符**与显式 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 -> elementelement 的内向关系显示外部来源
include element ->element 的外向关系显示目标
include <-> elementelement 的双向关系显示对称依赖

作用域视图中的要点: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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询