尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Dart SDK 实验特性开关(--enable-experiment)完全指南:进程规范、配置格式与源码实现

发布时间:2026/9/23 23:53:27

资讯中心
01
ARTICLE

Dart SDK 实验特性开关(--enable-experiment)完全指南:进程规范、配置格式与源码实现

Dart SDK 实验特性开关(--enable-experiment)完全指南:进程规范、配置格式与源码实现
编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载Dart SDK 通过实验特性开关experiment flags把进行中的未完成特性与已发布、受支持的特性明确区分开从而在不牺牲 dev 渠道质量的前提下持续落地新语言特性。本文以 docs/process/experimental-flags.md 为骨架完整讲解这套开关机制的背景、CLI 与 IDE 两种配置方式、单一事实来源文件 tools/experimental_features.yaml 的字段语义并结合仓库源码与 语言版本与实验特性交互文档 展开底层原理。读完你将对--enable-experiment的完整生命周期、生效链路与实战配置方法有体系化认知。为什么 Dart SDK 需要实验特性开关Dart SDK 通过多条渠道对外发布通过 Dart SDK 官方渠道安装说明 所在仓库对应的 Dart 官网通过 Flutter SDK 渠道随 Flutter 一起分发通过 Google 内部渠道。这些渠道使用各自不同的发布节奏让它们完全对齐并不现实。与此同时许多关注 Dart 最新进展的开发者会通过 dev 渠道 消费 SDK。因此必须假设任何 dev 渠道的构建都有可能最终以某种渠道变成正式发布的 SDK。这意味着 dev 渠道的质量必须保持高位且哪些特性已完成、受支持必须保持一致。另一方面团队又需要能够落地尚未完成的特性以支撑以下任务编排跨多个组件/领域的大型特性在特性完全完成之前进行自动化测试让合作伙伴团队提前预览未来特性让客户提前预览未来特性。这两类需求保持 dev 渠道高质量与允许落地不完整特性之间的张力正是实验特性开关机制存在的根本原因。整体方案所有进行中特性统一置于 flag 之后为了让已完成且受支持的特性与进行中的不完整特性可区分Dart SDK 规定所有进行中的特性都放在同一套 flag 集合后面。处于 flag 之后的特性其变更不视为破坏性变更即使该特性此前出现在某个稳定版 SDK 中并且随时可能被移除。关于破坏性变更的详细流程参见 breaking change 流程。凡是满足以下任一条件的新特性必须在 flag 后面开发只要可行所有破坏性变更breaking changes所有语言变更language changes。此外以下情况建议考虑放在 flag 后面落地较大的、用户可见的变更且该变更会以中间状态持续数周、甚至跨越数个版本所做的变更可能在数周甚至跨版本期间带来显著的负面性能影响。CLI 工具的 flag 格式与用法命名规则flag 由一个或多个单词组成单词之间用连字符-连接全部使用小写。这些 flag 的单一事实来源是一个共享的 .dart 文件详见下文单一事实来源一节各工具应提供查询框架使实现方可以方便地访问新 flag。--enable-experiment命令行传参flag 通过--enable-experiment选项传递给 CLI 工具。支持以下三种等价写法dart --enable-experimentsuper-mixins dart --enable-experimentsuper-mixins,no-slow-checks,preview-dart3 dart --enable-experimentsuper-mixins --enable-experiment no-slow-checks --enable-experiment preview-dart3即可以用一个传单个 flag可以用逗号分隔一次性传入多个 flag也可以重复使用--enable-experiment选项逐个传入。从源码看该选项在 pkg/front_end/lib/src/base/command_line_options.dart 中定义为Flags.enableExperiment --enable-experiment其解析结果是一个字符串列表OptionListString?因此三种写法在底层被统一规整为同一份列表。未知 flag 的容错行为如果用户传入了无法识别的 flag例如该 flag 已被移除或拼写错误工具必须向 stderr 打印提示但不失败dart --enable-experiment better-mixins Unknown experiment flag better-mixins.这种提示但不中断的设计是为了避免陈旧参数例如旧版 IDE 或脚本中残留的 flag 名直接打断用户工作流。IDE / 编辑器等 UI 工具的 flag 格式支持调用 Dart 工具的 IDE 和编辑器必须支持传递这些 flag且支持方式应当通用、灵活以便新增或移除 flag 时无需改动 UI。官方期望的形式有两种影响分析analysis的实验在analysis_options.yaml的单一enable-experiment:键下开启。例如同时启用super-mixins与no-slow-checksanalyzer: enable-experiment: - super-mixins - no-slow-checks影响启动/运行行为的实验在 IDE 特定的 Run Configuration 中通过传入与 CLI 相同的--enable-experiment选项开启。从源码看analyzer 在 pkg/analyzer/lib/src/analysis_options/analysis_options_file.dart 中定义了enableExperiment enable-experiment常量并在 pkg/analyzer/lib/src/analysis_options/analysis_options.dart 中把解析出的实验上下文contextFeatures纳入调试信息与缓存签名计算——也就是说实验开关的开启状态会直接影响分析结果的缓存键从而保证换一组实验开关就得到独立的分析结果。单一事实来源tools/experimental_features.yaml当前所有实验 flag 的定义集中在 tools/experimental_features.yaml 中各工具VM、CFE、Analyzer 等均以它为唯一权威输入。该文件头部注释明确写着Experimental features are described in docs/process/experimental-flags.md并且强调尽管名字叫实验它们并不局限于实验用途常常用于开启正在开发、尚未发布的特性或增强flag 预期生命周期较短某些特性可能被取消、永不发布。字段语义每个实验条目是一个 YAML map包含以下字段字段必填类型含义help是字符串该实验的人类可读描述。enabledIn否#.#主.次版本该实验随哪个 SDK 版本正式发布。指定后实验默认启用且无法关闭与 SDK 实际版本无关未指定则默认禁用可通过命令行 flag 开启。语言版本低于该值的库可通过// dart 2.12或 package config 关闭该特性。experimentalReleaseVersion否#.#从哪个版本起可以通过命令行 flag 启用该实验同时若 sdk/lib/_internal/allowed_experiments.json 中有对应条目该版本会让白名单内的库/包默认启用该实验。expired否布尔为true表示该 flag 不再能通过命令行启用条目将被安排从文件中移除缺省视为false。用户仍可指定该 flag但工具会给出已退休/被否决的警告并继续运行。validation否字符串一个用于验证的程序源码若特性启用程序打印feature enabled否则编译失败或抛异常。用于对每个实验运行通用测试。category否字符串实验所属类别如CFE、vm用于把只影响单个产品的特性从默认的language类别中剥离缺省为language会同时为 CFE 与 Analyzer 生成代码。channels否列表该实验可用的发布渠道如[main, dev]。文件顶部还有current-version字段当前仓库中为3.14.0指定正在开发的 Dart 版本未显式声明版本的 Dart 源文件默认归属此版本实验 flag 不会影响声明了更早版本的库。当前活跃实验一览节选截至当前仓库current-version: 3.14.0尚未发货的实验包括varianceSound variance、const-functions允许在 const 表达式中执行更多 Dart 代码、macros静态元编程experimentalReleaseVersion: 3.3.0、data-assetshooks 中的数据资源限 main/dev 渠道、unquoted-imports更简短的 import 语法、augmentations从外部增强声明experimentalReleaseVersion: 3.6.0、this-promotionthis的类型提升、static-extensions、anonymous-methods、single-combinators等同时保留了一个仅供测试的test-experiment无实际效果可用来测试 --enable-experiment 命令行功能。实验特性的生命周期从 Disabled 到 Retired结合 YAML 注释中的状态描述实验会依次经历以下状态Disabled禁用新实验加入文件时不写enabledIn与expired默认禁用但可通过命令行 flag 开启。实现团队在 flag 保护下构建支持用户可提前试用。Experimental release实验性发布当希望允许特定库/包默认启用该语言特性时向 sdk/lib/_internal/allowed_experiments.json 添加白名单条目并把experimentalReleaseVersion提升到最新版本。此时白名单内的库无需 flag其他库仍需传 flag 才能启用。Shipped已发布实验正式发布时添加enabledIn指明该语言特性所在 SDK 版本。此时命令行 flag 不再生效默认启用且无法关闭。历史实例包括non-nullableenabledIn: 2.12.0、records/patterns/sealed-class/class-modifiersenabledIn: 3.0.0、wildcard-variablesenabledIn: 3.7.0等。Retired / Rejected退休/否决在下一个稳定版中把expired置为true无论实验是已发布还是被否决flag 不再可启用条目随后从文件移除。当前仓库中primary-constructorsenabledIn: 3.13.0、experimentalReleaseVersion: 3.12.0与record-useenabledIn: 3.13.0处于已发布但尚未标记退休的状态符合注释中已发布的 flag 应在下一个稳定版标记退休的约定。语言版本与实验 flag 的关系要真正理解实验 flag必须结合语言版本机制详见 docs/process/language-versions-and-experiments.md每个 SDK 的主/次.0发布都会产生一个新的语言版本已发布语言版本的语义被完全固化。补丁版本如 2.5.1不产生新语言版本因此不能在补丁版里做破坏性语言变更。任何时刻都存在一个进行中in-progress的语言版本对应当前 dev 构建即下一个稳定版。它之下悬挂着一族实验语言experimental languages每个实验语言对应一种实验 flag 组合。例如 Dart 2.8 时代存在2.8、2.8non-nullable、2.8variance、2.8non-nullablevariance等多个并存语言。不存在已发布版本 实验的组合。2.7non-nullable是不存在的实验 flag 只对 in-progress 语言版本生效。某个版本一旦发布其周围的所有实验语言随之消失并迁移到新的 in-progress 版本周围。一个库选择语言版本遵循优先级规则// dart2.5注释 包内其他库由package_config.json指定pub 依据 pubspec 的 SDK 约束生成 无约束时默认当前 SDK版本。SDK 版本到语言版本的换算规则语言版本 工具报告的 semver 版本的主.次号。稳定版如 Dart 2.5.3 的语言版本是 2.5dev/edge 版则指向即将发布的稳定版语言版本。仓库中语言版本显式存放于tools/experimental_features.yaml的current-version避免因发布管理动作而意外变动。SDK 约束到语言版本的规则包默认语言版本 其 SDK 约束最小版本的语言版本。如2.8.0-dev.1 3.0.0会落在 2.8in-progress 版本。实验 flag 是全局的传入一组 flag意味着把所有使用 in-progress 语言的用户库当作使用对应实验语言。它会同时影响你项目里所有 2.8 库以及依赖包里所有 2.8 库。官方不支持用户程序随意混合多个实验语言如 2.8variance 库 import 2.8non-nullable 库因为组合的组合无法定义。核心库与特殊包有特殊权限已迁移的 SDK 核心库不需要用户传 flag 就能进入2.8non-nullable——工具在编译这些特定库时会自动处理Flutter 及其 API 导出的个别包如 vector_math也可通过白名单机制获得同样待遇。这些库仍须正确选择数字版本因为2.7non-nullable并不存在。实战在自己的库中使用实验特性以当年使用空安全non-nullable为例一套完整的操作流程是确认 SDK必须运行 dev 或 bleeding edge 构建。稳定版 Dart 不支持任何超出其语言版本的语言特性。声明目标语言版本在包的pubspec.yaml中把 SDK 约束的最小版本设为 in-progress 版本的 dev 版本environment: sdk: 2.8.0-dev.0 2.8.0最小约束可以更高如某个更晚的 dev 版关键是最小值必须是 2.8.0 的 dev 版本省略 SDK 约束对应用包可行但库包必须声明约束才能发布。最大约束较低2.8.0是为正式发布前留出可破坏的余地若声明3.0.0也仍然可用只是承担更大兼容承诺。开启实验 flag调用工具时传入--enable-experimentnon-nullable同时在analysis_options.yaml中做同样配置以获得 IDE 分析支持analyzer: enable-experiment: - non-nullable验证可借助 YAML 中声明的validation程序如int? a null; print(feature enabled);快速判断特性是否生效。当一个实验随稳定版发布时若你的约束形如2.10.0-dev.0 2.10.0只需把最大约束上调到包含 2.10.0 并验证兼容性若形如2.10.0-dev.0 3.0.0则无需改动若形如2.8.0 3.0.0则你的包停留在旧语言版本、相当于选择退出该特性。从源码看 flag 的完整生效链路YAML → 生成代码tools/experimental_features.yaml 是唯一手写源。修改后需分别运行生成命令更新三端analyzerdart pkg/analyzer/tool/experiments/generate.dart及dart pkg/analyzer/tool/api/generate.dart、kernel/CFEdart pkg/front_end/tool/cfe.dart generate-experimental-flags与dart pkg/front_end/tool/update_expectations.dart、VMdart tools/generate_experimental_flags.dart见 tools/generate_experimental_flags.dart。若新增 flag 不在字典序末尾还需在 pkg/analyzer/lib/src/dart/analysis/driver.dart 中提升DATA_VERSION因为该值参与分析缓存键的版本化。生成的 flag 定义pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart 中的ExperimentalFlag类承载name即--enable-experiment使用的名字、isEnabledByDefault、isExpired、experimentEnabledVersion默认启用所需的最低版本未默认启用时为当前语言版本与experimentReleasedVersion允许用 flag 启用并作用于白名单库的最低版本。文件头部注明本文件由生成器产生请勿手改。CLI 解析见 pkg/front_end/lib/src/base/command_line_options.dart--enable-experiment被解析为字符串列表。Analyzer 配置见 pkg/analyzer/lib/src/analysis_options/analysis_options.dartenable-experiment键解析出的实验上下文参与缓存签名与调试输出。白名单机制sdk/lib/_internal/allowed_experiments.json 用experimentSets如sdkExperiments、macros为 SDK 库与特定包如json包启用macros集合声明默认实验配合experimentalReleaseVersion字段工作。诊断提示当用户在代码中使用了需要实验开关才能编译的语法时analyzer 的诊断信息会提示Try passing the --enable-experiment{0} command line option.见 pkg/analyzer/lib/src/diagnostic/diagnostic.g.dart把如何开启直接反馈给开发者。注意事项与最佳实践flag 保护下的特性随时可能被破坏或移除即使某特性曾在稳定版 SDK 中亮相只要它仍处于 flag 之后其变更就不算破坏性变更。生产代码不应依赖此类特性。不要对已发布语言版本启用实验实验 flag 只作用于 in-progress 语言版本希望不受某个实验影响的用户库应确保它不落在 in-progress 版本上例如通过显式语言版本注释或 SDK 约束。升级到稳定版时注意约束调整实验特性随稳定版发布后flag 将失效默认启用届时需按上一节规则调整 pubspec 约束。保持 flag 集合的整洁新增实验时遵循 tools/experimental_features.yaml 头部注释中的生成与版本号维护步骤已发布 flag 应在下一个稳定版标记expired: true以便后续清理。关于发布渠道与分支节奏的更多背景可参考 docs/Branches-and-releases.md关于破坏性变更的完整流程参见 docs/process/breaking-changes.md语言版本与实验交互的完整模型参见 docs/process/language-versions-and-experiments.md。赞分享编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载相关推荐Dart SDK 实验特性开关Experiment Flags完全指南从新增旗标到代码生成与生命周期管理Dart SDK 实验特性开关Experiment Flags完全指南从新增旗标到代码生成与生命周期管理 导读 本文以 pkg/analyzer/doc/编程语言编译器语言运行时标准库开发工具kOps 实验特性开关KOPS_FEATURE_FLAGS完全指南从开启方式到源码实现kOps 实验特性开关KOPS_FEATURE_FLAGS完全指南从开启方式到源码实现 导读 kOpsKubernetes Operations通过环云原生集群管理运维IaCBazel 模块注册表Registry完全指南格式规范、源码实现与配置实战Bazel 模块注册表Registry完全指南格式规范、源码实现与配置实战 本文聚焦 Bazel 外部依赖解析的核心基础设施——模块注册表registr构建工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。