mcpField
C
CSharp.Refactor

CSharp.Refactor

本地服务
github.com/Thorium开发工具21 周前更新

关于 CSharp.Refactor

CSharp.Refactor 是面向 C# 开发者的离线 Roslyn 分析器和命令行工具,提供关注正确性、性能和惯用写法的重构建议。它支持编辑器快速修复及批量、经构建验证的修改;建议仅供参考,不会阻止构建。

主要功能

  1. 01基于 Roslyn 的离线 C# 分析
  2. 02编辑器灯泡修复和命令行批量修改
  3. 03试运行、规则筛选和 API 修改控制
  4. 04构建验证及最终构建失败时回滚
  5. 05支持基线的 SARIF、HTML 和 CSV 报告

适用场景

  1. 01在修改项目之前审查重构建议
  2. 02对整个解决方案应用指定修复并验证构建
  3. 03在 CI 中以 SARIF 上传分析结果

MCP 相关

`csharp-refactor` 命令可通过标准输入输出作为 MCP 服务运行,提供 `analyze` 和 `list_rules`。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
nugetcsharp-refactor0.1.20

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

CSharp.Refactor

C# 的小妹妹 FSharp.Refactor

为 C# 提供函数式重构建议,使用 F# 基于 Roslyn 实现。 这些规则关注正确性、经测量的性能和清晰、符合习惯的 C# 写法;刻意不涉及命名、布局或约定。

  • 在编辑器中提供快速修复灯泡(Visual Studio、VS Code、Rider,以及任何承载 Roslyn 分析器的环境)
  • 提供命令行工具,可批量应用建议并验证构建

建议的严重性为 Info:它们指出改进机会,而非缺陷,绝不会阻止构建。


使用方法

该工具完全离线:开发过程中使用了 AI,但它本身不使用 AI。

快速开始

无需配置——该工具会读取你的项目,报告将要进行的更改,并且只有在你明确要求时才会编辑:

dotnet tool install --global csharp-refactor
csharp-refactor Your.csproj --dry-run --api-changes

它会列出所有将要进行的修复及其文件和位置,不会写入任何内容。确认列表无误后,去掉该标记即可应用修复:

csharp-refactor Your.csproj --api-changes

如果你不想更改公共方法或 API,请去掉 --api-changes:

csharp-refactor Your.fsproj

如果项目当前无法构建,它会拒绝运行;每轮处理后都会在内存中重新编译,最后实际构建项目,如果构建失败则撤销修复。

如需在输入代码时使用灯泡,请参阅下方的 VS Code / Ionide 和 Visual Studio IDE 插件说明。
image
dotnet 工具支持 MCP,可用于 Agent 场景。

使用工具:

传入任意目标——工具会根据路径判断类型:

Your.csproj一个项目
Thing.cs一个源文件——会找到并分析其所属项目,但只编辑该文件
Your.sln、Your.slnx解决方案列出的所有 C# 项目
src/该目录中的解决方案,或其下的项目
"src/**/*.csproj"glob 匹配的所有内容
build.csx一个 C# 脚本——使用它自己的编译机制(#r、#load、NuGet 缓存),完全不使用 MSBuild;传入目录也会一并处理其中独立的脚本
C:\git一个包含多个检出项目的工作区:分别分析每个项目,并汇总到一份报告中

编辑器和 CI 设置

分析器以 CSharp.Refactor.Analyzers 的形式发布,是一个普通的 Roslyn 分析器包。将它引用到要分析的项目中后,每种宿主环境——dotnet build、Visual Studio、VS Code 的 C# 扩展、Rider——都会自动加载它:

<PackageReference Include="CSharp.Refactor.Analyzers" Version="*" PrivateAssets="all" />

该包是开发依赖项:只会提供提示和快速修复,不会有任何内容进入编译输出或 bin 目录。

Visual Studio 2022 / 2026

安装 CSharp.Refactor 扩展: 在 IDE 中打开的每个 C# 项目都会获得建议和 Ctrl+. 修复,无需更改项目,也不会影响构建。它的“工具”>“CSharp.Refactor”菜单会在打开的解决方案上运行 csharp-refactor 工具(应用或试运行,可带或不带 --api-changes),生成 SARIF 报告,打开说明页面和 .editorconfig 代码块——也就是 VS Code 扩展的命令在 Visual Studio 中的版本。也可以使用上文的包引用;两种方式都有效,同时使用时每项发现只会显示一次。

VS Code

安装 CSharp.Refactor 扩展。 它内置了分析器,并会在征得你同意后,通过 MSBuild 的用户级 ImportBefore 挂钩将分析器接入此计算机上的每个 C# 项目(在你的用户配置目录下创建一个 props 文件,可通过命令撤销)。也可以使用包引用。

CI

分析器在编译器内运行,因此构建无需额外工具即可将发现结果写入 SARIF:

dotnet build -p:ErrorLog=findings.sarif

该工具自身的报告包含更多信息——将修复作为建议更改、上下文 片段和稳定指纹——并可搭配 --dry-run 用作 lint 门禁:

      - run: dotnet tool install --global csharp-refactor
      - run: csharp-refactor src/Your.csproj --dry-run --report findings.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: findings.sarif
          category: csharp-refactor

无论是否发现问题,试运行都会以 0 退出;--fail-on-findings 会在筛选后仍存在发现结果时以 3 退出,而 --baseline 会将其变为 棘轮:较早报告中已有的发现结果既不会被报告,也不会被修复,只会显示新的发现结果。

从命令行应用修复

csharp-refactor Your.csproj [--dry-run] [--codes CR0090,CR0103] [--categories correctness,performance] [--api-changes]
标志
--dry-run仅报告:列出所有将要进行的修复,不写入任何内容。
--codes CR0090,CR0103将运行限制为指定规则;其他规则完全不会运行。指定规则即表示要求运行该规则:优先级高于该规则的默认关闭状态和配置中的 none。
--categories <list>将运行限制为指定规则类别:correctness、performance、idiom、cosmetic。其他类别的规则不会运行。对于你不维护的代码库,correctness,performance 是值得提交拉取请求的范围。
--define <symbols>此次运行定义的预处理器符号,类似于 csc -define: 或 DefineConstants 条目:可重复使用,也可用 ; 或 , 分隔(--define:A 和 -d:A 也可用)。这些符号会添加到每个项目自身的 DefineConstants 中,DEBUG、TRACE 和项目常量会保留。参见 由 #if 控制的代码。
--api-changes同时应用会更改内部或公共签名和结构的修复,并重写整个解决方案中的调用位置(引用校验器会在每个项目中查找这些位置;VB 项目中的调用方会阻止应用修复,F# 使用方会阻止更改接口)。不使用此选项时,这些修复会被暂缓并计数。
--report <file>写入所有发现的问题:.sarif、.html(自包含页面)或 .csv。
--baseline <sarif>设定整改门槛:指纹出现在此较早报告中的问题既不会报告,也不会修复。
--fail-on-findings若筛选后仍存在任何问题,则以 3 退出。退出码约定:0 表示干净,1 表示失败,2 表示用法错误,3 表示发现问题。
--notes [on|off|only]在行内列出没有修复项的提示;only 用于审查,不会写入任何内容。默认情况下,运行会打印修复项和每个类别的提示计数;报告和 JSON 始终包含这些提示。
--format json输出机器可读内容;进度文本会输出到 stderr。
--rules打印规则目录。
--create-config将包含所有规则和键及其默认值的注释代码块追加到目录的 .editorconfig 中。
--mcp通过 stdio 将 analyze 和 list_rules 作为 MCP 服务提供,并在多次调用间复用同一个已预热工作区。
--parse-only不加载引用:仅运行语法规则。不能替代实际运行。
--max-passes <n>修复后重新分析的迭代次数(默认值为 5)。第一轮之后,每轮仅重新分析上一轮编辑过或暂缓修复的文件。

项目通过 MSBuildWorkspace 加载,包括任何目标框架的 SDK 风格项目(也包括 net48),以及项目列出的所有框架变体。对于传统项目(<Project ToolsVersion="4.0" …>,且包含显式 <Compile> 项),如果 .NET Framework 构建主机没有响应,则会直接从项目文件读取:编译项、定义、存在的 HintPath 引用、目标框架包程序集和项目引用。如果缺少构建树(例如自定义 .targets 添加的引用或同级 bin),某些类型将无法解析;运行会说明无法解析的类型数量,类型规则会在类型未知的位置停止运行,内存检查会确保错误数量不增加。如果基线构建成功,最终构建会通过 Visual Studio 的 MSBuild.exe 运行;否则运行结果仅在内存中验证,并会明确说明。解决方案中被其他项目引用的可执行项目(例如其测试项目)并非叶项目:除非使用 --api-changes,否则其公共结构会保持不变;更改项目的所有依赖项目也会一并构建。

C# 脚本(.csx)会作为独立编译单元处理:文件按脚本解析,运行时本身作为引用,#r 会根据脚本所在目录、运行时和 NuGet 缓存解析(#r "nuget: Name, Version"),#load 则由编译器读取以提供上下文(被加载文件仅在作为独立目标进行扫描时才会编辑,扫描目录时则会遍历所有未归属项目的脚本)。脚本不会被构建,因此运行结果会在内存中验证:错误数量不得增加,脚本宿主的全局变量(Args)在前后两侧都计为错误。

#if LOCAL_BUILD 下的代码

被未定义预处理符号控制的代码根本不会进入语法树:工具既不会分析它,也看不到其他位置的修复会对它产生什么影响,而且验证构建也不会编译它。例如,仓库将本地开发路径放在 #if LOCAL_BUILD 下时,可以在运行时指定符号:

csharp-refactor Your.sln --define LOCAL_BUILD        # or --define:LOCAL_BUILD, -d:LOCAL_BUILD
csharp-refactor Your.sln --define "LOCAL_BUILD;CI"   # several at once

也可以在 .editorconfig 中为每次运行指定一次(csharp_refactor.defines = LOCAL_BUILD,见下文)。运行会同时使用两种方式,并在开始时说明哪些符号处于启用状态,以及每个符号的来源。符号会在每个项目定义的基础上追加,效果与在环境中设置 DefineConstants 后运行 dotnet build 一样:SDK 的 DEBUG/TRACE、目标框架的 NET8_0_OR_GREATER 以及项目自己的 $(DefineConstants);FOO 都会保留。(-p:DefineConstants=LOCAL_BUILD 不行:全局属性会替换所有这些值。)运行启动的每次 MSBuild——工作区的设计时构建、还原、验证构建——都会以这种方式获得这些符号;已加载的 C# 项目、旧版项目和 .csx 脚本也会在其解析选项中获得这些符号,因此即使项目直接赋值 DefineConstants,也仍会使用这些符号进行分析。如果某个脚本的 #r 无法解析,而另一个 #r 位于 #if LOCAL_BUILD 下,工具会提示传入 --define LOCAL_BUILD。

配置

规则的配置方式与所有 Roslyn 分析器相同,使用 .editorconfig,并以最近的节为准:

[*.cs]
dotnet_diagnostic.CR0103.severity = none          # off
dotnet_diagnostic.CR0006.severity = suggestion    # a default-off rule, on
csharp_refactor.CR0006.then_at_least = 30         # a rule's knob

csharp_refactor.public_api   = false              # nothing links to this assembly
csharp_refactor.api_changes  = true               # --api-changes as a standing decision
csharp_refactor.suppressions = no-correctness     # all | no-correctness | none
csharp_refactor.skip_microsoft_duplicates = true  # the Microsoft analyzers run here: skip what they already report
csharp_refactor.ignore_paths = generated;external/imported
csharp_refactor.defines = LOCAL_BUILD             # like --define on every run

csharp_refactor.defines 是运行级别的键:每次运行时,它都会从距离目标最近的 .editorconfig 读取(遇到 root = true 即停止向上查找),并追加到 --define,而不会替换它。

csharp-refactor --create-config 会为你写入配置块,其中每个值都设为此版本的默认值,因此在你编辑配置项之前不会产生任何变化。每条规则的选项都位于其严重性配置行之后,并采用默认值;默认值并非单一值的选项(CR0023 的测量下限、规则的 wrap_column,其默认值会回退到文件的 max_line_length)会以注释形式写入。

工具和编辑器都不会触碰生成文件:位于 bin、obj、node_modules 或 .git 下的文件,名为 *.g.cs、*.designer.cs、*.generated.cs 或 *.g.i.cs 的文件,列在 ignore_paths 中的文件,以及标头注明 <auto-generated>(例如 T4 模板、resx 设计器、SDK 的 AssemblyInfo)或“This code was generated by”的文件。

单条发现可通过 Roslyn 自带的方式静默处理,例如 #pragma warning disable CR0090、[SuppressMessage] 或将严重性设为 none;编辑器会原生遵循这些设置。suppressions 策略决定工具的行为:no-correctness 仍会报告被抑制的正确性问题(并且绝不会自动修复),none 会报告所有被抑制的问题;--honor-suppressions 可在单次运行中覆盖这两种设置。运行摘要会统计被抑制而未报告的问题。

如果某条规则与 Microsoft 分析器规则(CA2213、CA1031、CA2000 等)重叠,那么只要文件的有效配置启用了相应的 Microsoft 规则,该规则就会对相应代码形态让出处理权,避免重复报告和反复变更。Rules.md 列出了每条规则对应的 Microsoft 规则。

将警告视为错误:工具使用与你的 CI 构建相同的设置(TreatWarningsAsErrors、WarningsAsErrors、.editorconfig 严重性)。如果某项修复会触发分析器错误,工具会保留该文件不变,指出分析器和规则,并告知你需要修改什么。使用 可仍然应用这些修复(警告仍会显示),也可以使用 为所有人静默该分析器。


改进它

构建和测试

dotnet build
dotnet test

提交前:

dotnet tool restore
dotnet fantomas src tests
dotnet dotnet-fsharplint lint src/CSharp.Refactor.Analyzers/CSharp.Refactor.Analyzers.fsproj

测试框架会将 C# 字符串字面量编译到正在运行的框架中,运行纯规则,将每项修复作为文本应用后重新编译;宿主测试会通过 Roslyn 驱动真实的 DiagnosticAnalyzer 和 CodeFixProvider;工具测试则会让合成项目通过 MSBuildWorkspace。tests/run-tests.ps1 会运行所有测试。benchmarks/PerfClaims 保存了每项性能声明对应的前后对比。

多行输入通过 csharp helper 作为缩进块提供(tests/CSharp.Refactor.Tests/TestSource.fs):闭合引号的缩进会从每一行中移除,因此规则看到的类从第 0 列开始,而 Fantomas 可以移动该代码块而不改变内容。

let source =
    csharp
        """
        class C
        {
            int F(int x) => x + 1;
        }
        """

fires 3 "CR0046" source 会返回规则的建议并断言其数量;assertFired 对手动筛选的列表执行相同操作。如果不匹配,它会列出每条建议触发时对应的文本,因此失败信息会指出遗漏的位置,而不仅仅是给出一个数量。

必须是常量的字面量(属性参数、[<Literal>]、printf 格式),或者包含制表符、\r 或尾随空白的字面量,仍使用转义的 "...\n..." 字符串。

除基于示例的测试套件外,tests/CSharp.Refactor.PropertyTests 还是一套 FsCheck 测试,用于测试生成的程序:一类成员各自按某条规则的形状构造;方法体则包含由三个整数构成的布尔项,并以 Roslyn 语法树上的解释器作为判定基准。其属性体现了规则承诺的不变量——每项修复(包括仅适用于编辑器的替代方案)都能保持程序可编译;面对从受损文本恢复出的编译单元时,不会有规则抛出异常;逐项应用修复最终会达到固定点;布尔表达式和控制流重写(CR0001、CR0005、CR0007、CR0008、CR0011)在每一步都保持方法的真值表不变。生成器覆盖了 124 条规则中的 121 条(凡是 CR0017 与 CR0160 都能读取同一种形状时,前者都会被后者涵盖;CR0156 和 CR0158 需要 C# 15,而测试框架无法解析该版本),并且有一项覆盖率测试会逐一尝试每种形状,再尝试它们的组合:如果某种形状不再触发它原本针对的规则,测试会指出具体是哪一种。另有两项属性测试会按照真实文件的样子修饰程序——在成员周围加入 #region,在成员中加入 #if 和注释,使用 CRLF、制表符和 #pragma——并要求每项修复都能编译且保留原有内容(不吞掉指令或注释,也不在 CRLF 文件中留下裸 LF);同时还会在从 C# 7.3 到 13 的每个语言版本下编译,并要求修复所用语法不超过文件本身的语言版本。两项测试都会对每种形状及随机程序进行确定性测试。能够编译却改变含义的重写无法由编译不变量发现,因此只要可行,形状都会包含一个诱饵:CR0100/CR0101 的形状会调用一个 FormattableString 重载标记了 [Obsolete(error)] 的方法,因此会重新绑定该调用的插值会导致编译错误;CR0082 的形状会将一个元组传给 object,重新定型后则无法编译。无法通过诱饵表达的情况(例如由带有行为的类型组成的记录,或将记录放入异常消息中)仍由基于示例的测试套件覆盖。

设计原则

  1. 绝不破坏用户代码。 只有在能够证明安全时才提供修复;对于边界情况,不提供建议。无需编译也必须确保修复正确:同一修复会在编辑器中运行,而编辑器不会验证它。
  2. 优先添加保护条件,而非移除规则。 不安全的重写必须通过类型化证明确认代码形态安全;证明不成立时则不执行。绝不删除规则或一概禁用规则。
  3. 尽量减少编辑。 修复采用基于范围的文本编辑;编辑范围之外的格式保持不变。
  4. 核心逻辑保持纯粹,适配器保持精简。 每条规则都是一个纯函数,接收语法树和语义模型并返回建议;Roslyn 分析器、修复提供程序和工具都只是基于该函数的单行适配器。
  5. 提示只指向符合习惯的 C# 写法。 可逆的风格选择应交由 IDE 的重构功能处理,而非通过诊断提示。

完整的安全模型、让步门控、计划中的规则目录以及与 Microsoft 分析器之间的关系,请参阅 DESIGN.md。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。