Ohhnews

分类导航

$ cd ..
Jetbrains Blog原文

Rider将重构引擎交给AI代理:更安全、更快、成本更低

#jetbrains rider#ai代理#代码重构#c##开发效率

我们追踪了一个前沿模型完成十五个 C# 重构任务的过程,并统计了它调用了什么。它向交互式命令输送文本 468 次。调用 git 422 次、sed 392 次。运行 dotnet build 163 次。在 2,513 次工具调用中,它执行结构化重构操作的次数恰好为零。不是因为它刻意回避:而是它根本没有可调用的重构操作。

Rider 拥有数十种 C# 重构,而从 2026.2.1 版本开始,代理可以直接调用这些重构,而不是用近似方式模拟。载体是内置技能 refactoring-code。它随 IDE 一起提供,无需开启任何开关;只要代理被要求重构 C# 代码,它就会自行激活。我们在启用该技能的情况下,让同一个模型再次完成同样的十五个任务。

Refactoring-code 技能,随 JetBrains Rider 内置提供

  • 任务中位耗时:之前 157.9 秒 → 之后 26.6 秒,提速 83%
  • 每个已解决任务成本:之前 USD 0.52 → 之后 USD 0.19,便宜 64%
  • 每个任务工具调用数:之前 17.0 → 之后 6.2,减少 63%

中位数基于十五个 C# 重构任务,每个任务使用相同模型和相同提示词大约运行十次。两组之间的唯一区别是代理能否调用 Rider 的重构引擎。

编译器真的应该当裁判吗?

163 次构建的数字一开始让我们停下思考。但随后我们意识到,代理编译并不是为了检查成品,而是为了弄清楚它的上一次编辑到底做了什么。一次正确的重命名需要处理重载解析、分部类、显式接口实现和文档引用,并且要知道名为 Order 的类型和注释中的单词 “order” 之间的区别。这些信息都不是正则表达式能恢复的,所以代理只能先猜测文本,再让构建结果给猜测打分。

Rider 不需要猜测,因为它有已解析的语法树。其重构引擎由 ReSharper 提供支持,基于驱动 IDE 自身检查和导航的同一模型工作:它知道每个标识符绑定到哪个声明、每个调用解析到哪个重载、以及解决方案中每个引用位于何处。代理需要一次次通过构建来重建的知识,正是 IDE 一次就能应用的知识。

我们的评估方法

Rider 有数十种 C# 重构,在测试 refactoring-code 技能的效果时,我们并未试图覆盖全部。我们评估了八种,因为它们拥有最清晰的契约:有明确目标、明确结果,并且在变更不安全时拒绝执行。正是这些操作的成功与失败毫无歧义,才让它们首先值得被测量。

  • rename_refactoring:重命名一个符号及其所有引用
  • extract_method:将一段语句提取到新方法中
  • extract_interface:从现有类型派生接口
  • extract_base_class:将成员提升到新的基类中
  • change_api_signature:修改参数并更新所有调用点
  • move_type_to_namespace:移动类型并修复 using 指令
  • reorganize_namespaces:让命名空间与文件夹结构保持一致
  • safe_delete:仅在没有依赖项时删除符号

十五个任务覆盖了这八种操作,其中大部分有两种变体:一个直接了当的案例,以及一个调用点更多、依赖关系更纠缠的困难案例。

两组都通过 Codex CLI 运行 gpt-5.5,每个任务大约十次;它们之间的唯一区别是 refactoring-code 是否可用。

耗时、成本和工具调用次数来自记录轨迹,下面的比较使用配对置换检验。

代理配备 Rider 技能后能做什么

技能就位后,不再需要构建来当裁判:dotnet build 从 163 次下降到 3 次。代理围绕猜测搭建的脚手架也随之消失,整个评估中的工具调用总数从 2,513 次下降到 926 次。

代理并没有停止编辑文本。sed 仍然是最常用的工具,八种重构操作在 926 次调用中仅占 167 次。改变的是分工:普通编辑仍留在编辑器媒介中,而结构性变更——那些后果会波及代理视野之外的操作——交给引擎处理。

时间与成本

任务中位耗时从 157.9 秒下降到 26.6 秒。第 95 百分位下降得更明显,从 346.4 秒降到 56.9 秒,因为最慢的几次运行正是被困在“编辑—构建—读取错误”循环中的那些,而这些运行已经不存在了。在配对置换检验下,这两项改进都具有统计显著性。

成本随耗时同步下降。每个任务的中位成本从 0.33 美元降至 0.12 美元,每个已解决任务成本从 0.52 美元降至 0.19 美元,token 消耗大约减少一半:每个任务的输入从 436,745 降至 208,524,缓存读取从 2,973,158 降至 1,257,600,输出从 32,532 降至 15,538。

各任务结果

技能完胜的场景:从最慢的任务开始

以下八个任务中,启用技能的一组更快、更便宜,且工具调用数没有增加,两组也都通过了测试。两组各取一次代表性运行,按基线耗时排序。

时间(秒)

任务未使用技能使用 refactoring-code变化
extract-base-class-2337s20s-94%
move-type-to-namespace-1297s24s-92%
rename-1192s35s-82%
reorganize-namespaces-1160s25s-84%
rename-2157s24s-85%
extract-method-1157s25s-84%
reorganize-namespaces-226s11s-57%
safe-delete-121s19s-9%

工具调用数

任务未使用技能使用 refactoring-code变化
extract-base-class-2243-88%
move-type-to-namespace-1257-72%
rename-1217-67%
reorganize-namespaces-1183-83%
rename-2167-56%
extract-method-1164-75%
reorganize-namespaces-2132-85%
safe-delete-1106-40%

成本(USD)

任务未使用技能使用 refactoring-code变化
extract-base-class-21.1460.090-92%
move-type-to-namespace-11.0460.160-85%
rename-10.9860.137-86%
reorganize-namespaces-10.3850.134-65%
rename-20.3270.162-50%
extract-method-10.4970.098-80%
reorganize-namespaces-20.1810.078-57%
safe-delete-10.1080.088-18%

十五个任务中有八个达到了这个标准,而基线耗时超过两分钟的六个任务改善了 82%–94%。其余七个未包含在内:其中两个两组都未解决,一个仅在没有技能时被解决,另外四个原本已经足够快,调用 IDE 并不划算。本文其他地方引用的汇总数字覆盖全部十五个任务。

数字说明行为发生了变化,但没有说明是如何变化的。因此下面从该任务集中选取一个任务,分别展示两组逐调用的情况。

左侧是这篇文章一直在描述的循环:代理找到类,编辑文本凭空创建一个基类,然后花十一次构建与编译器协商这些编辑破坏了什么。右侧是启用技能后执行同一任务:同样先搜索目标,然后调用一次 extract_base_class,再看一眼 diff。

我们选择“提取基类”作为示例,因为这是评估中最悬殊的单次变化:从 337 秒、24 次工具调用,变成 20 秒、3 次工具调用。但在技能获胜的所有地方,变化的形态都是一样的。

一个任务,两条轨迹

以“提取基类”作为典型示例

一个测试用例,并排展示代理在有和没有 Rider 专用技能时如何执行重构。在没有技能时,它是该任务集中最慢的一项;在有技能时,它是改善幅度最大的一项。

未使用技能

时间 336.7s · 调用 24 · 成本 USD 1.15

rg "class ReportExporter" -n src/
find . -name "*.cs" -path "*Reporting*"
nl -ba src/Reporting/ReportExporter.cs
grep -rn "ReportExporter" src/ tests/
apply_patch src/Reporting/ExporterBase.cs
sed -i 's/class ReportExporter/\& : ExporterBase/' src/Reporting/ReportExporter.cs
dotnet build
error CS0534: does not implement inherited abstract member
error CS1729: no constructor takes 2 arguments
sed -i 's/public ReportExporter(/protected ReportExporter(/' src/Reporting/ExporterBase.cs
dotnet build
error CS0122: inaccessible due to its protection level
... 9 further edit-and-build cycles ...
dotnet build
Build succeeded

使用 refactoring-code

时间 19.8s · 调用 3 · 成本 USD 0.09

rg "class ReportExporter" -n src/
execute_tool::extract_base_class
target: ReportExporter
name: ExporterBase
members: Format, WriteHeader, Dispose
created src/Reporting/ExporterBase.cs
updated 4 files, 11 references rewritten
git diff --stat
5 files changed, 47 insertions(+), 23 deletions(-)

想自己尝试只需要一个提示词。升级到 Rider 2026.2.1,打开一个 C# 解决方案,然后让代理重命名、提取或移动某个东西。技能会自动激活。指明具体操作会有帮助:“从 OrderProcessor 提取一个接口”比“清理这个类”更能让代理找到确切目标。

这是我们测量过的第三个此类技能。前两个为代理提供了覆盖率数据性能分析器输出。Rider 内置了越来越多基于同一理念的代理技能:让代理利用 IDE 自身的智能,而不是重构这些能力,从而用更少的 token 获得更好的结果。请在真实代码库上试试,并告诉我们效果如何。

下载 JetBrains Rider