Skip to content

Conversation

@zombieJ
Copy link
Member

@zombieJ zombieJ commented Dec 8, 2025

ref ant-design/ant-design#56102

react-component/field-form#761 中更新了调用逻辑,以裁剪输出内容。但是对于 Form.List 比较特殊的一个点则是对于 List 项目的增减操作是覆盖操作,而对于 List.Item 操作则是更新操作。所以 merge 直接的替换更新会导致丢失内容。这里添加一个函数以支持合并更新的逻辑。

Summary by CodeRabbit

发布说明

  • 新功能

    • 增强对象深度合并:引入可配置的深度合并函数,支持自定义数组合并策略(prepareArray)。
    • 新增对外可用的 deepMerge 接口,并保留原有 merge 封装以确保向后兼容。
  • 测试

    • 新增测试覆盖自定义数组合并逻辑及 deepMerge/merge 行为。

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
util Ready Ready Preview Comment Dec 8, 2025 8:56am

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Warning

Rate limit exceeded

@zombieJ has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 10 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ce49d32 and 5c8481b.

📒 Files selected for processing (3)
  • src/index.ts (1 hunks)
  • src/utils/set.ts (3 hunks)
  • tests/utils.test.ts (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

src/utils/set.ts 中新增并导出 deepMerge(接收 sources 与可选 config.prepareArray),引入导出类型 MergeFn 以定制数组合并;添加兼容性封装 merge(...sources) 委托给 deepMerge;同时更新 tests/utils.test.ts,新增针对 prepareArray 的测试覆盖并导入 deepMerge

Changes

内聚体 / 文件(s) 变更摘要
核心功能实现
src/utils/set.ts
新增导出类型 MergeFn;新增 deepMerge<T>(sources, config?) 实现递归合并(对象/数组、循环检测、visited 跟踪);支持可配置数组合并 via prepareArray(默认行为为 finalPrepareArray);新增 merge<T>(...sources) 包装函数委托给 deepMerge 以保持向后兼容
测试覆盖
tests/utils.test.ts
更新导入以包含 deepMerge;新增测试用例验证带 prepareArray 配置的 deepMerge 行为(数组元素的自定义合并)并保留原有合并测试

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 分钟

  • 建议重点审查:
    • src/utils/set.ts 中的循环检测(visited 跟踪)与引用/相等判定逻辑
    • prepareArray 回调的默认行为与何时调用(确保在各种数组场景下正确触发)
    • merge(...sources) 在空参数或非对象输入时的边界行为与向后兼容性
    • 新增测试是否覆盖嵌套数组/对象与潜在循环引用场景

Poem

🐰 轻嗅代码的青草香,
深度合并跳一趟,
数组回调排成行,
循环护栏稳当当,
小兔鼓掌庆辉煌! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题 'feat: support custom merge' 准确概括了主要变更:引入可配置的深度合并功能(deepMerge函数和MergeFn类型),但略显简洁。

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @zombieJ, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求引入了一个新的 deepMerge 工具函数,旨在增强对象的合并能力,尤其解决了在 Form.List 等组件中数组直接替换可能导致数据丢失的问题。新的函数允许在合并过程中自定义数组的准备逻辑,从而提供了更精细的控制并防止了意外的数据丢失。

Highlights

  • 引入 deepMerge 函数: 新增了一个名为 deepMerge 的工具函数,它提供了更强大的深度合并能力,特别是允许通过 prepareArray 配置项自定义数组的合并策略。
  • 解决数组合并问题: 针对 Form.List 等场景中数组元素更新可能导致数据丢失的问题,deepMerge 允许开发者传入自定义的 prepareArray 回调,从而实现智能的数组合并而非简单覆盖。
  • 保持 merge 函数兼容性: 原有的 merge 函数现在作为 deepMerge 的一个兼容性封装,确保了现有代码的平滑过渡和调用方式不变。
  • 增强测试覆盖: 为 deepMerge 函数添加了新的单元测试,特别验证了其自定义数组合并逻辑的正确性。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

这个 PR 引入了 deepMerge 功能以支持更灵活的对象合并策略,特别是针对数组的合并,解决了 Form.List 中数据可能被意外覆盖的问题。整体实现思路清晰,通过重构现有的 merge 函数来保持向后兼容性,这是一个很好的实践。我注意到一些可以改进的地方,主要在于提高代码的清晰度和可读性,具体请看我的评论。

@codecov
Copy link

codecov bot commented Dec 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.53%. Comparing base (4d24a06) to head (5c8481b).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #711      +/-   ##
==========================================
+ Coverage   90.47%   90.53%   +0.06%     
==========================================
  Files          37       37              
  Lines         903      909       +6     
  Branches      311      299      -12     
==========================================
+ Hits          817      823       +6     
  Misses         84       84              
  Partials        2        2              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/utils.test.ts (1)

256-287: 测试逻辑正确,验证了自定义数组合并行为。

测试用例有效验证了 prepareArray 配置项的功能。不过 prepareArray 回调只使用了第一个参数 srcVal,忽略了第二个参数 tgtVal。考虑补充一个使用两个参数的测试用例,以更完整地展示 API 能力。

示例补充测试:

it('deepMerge with prepareArray using both params', () => {
  const src = { list: [1, 2] };
  const tgt = { list: [3, 4] };

  const merged = deepMerge<any>([src, tgt], {
    prepareArray: (originVal, newVal) => {
      return [...(originVal || []), ...newVal];
    },
  });
  expect(merged).toEqual({ list: [1, 2, 3, 4] });
});
src/utils/set.ts (1)

70-70: 参数命名可以更清晰。

srcValtgtVal 的命名容易与 deepMergesources 参数混淆。结合 line 107 的实际调用 finalPrepareArray(originValue, value),建议改为更具描述性的名称:

-export type MergeFn = (srcVal: any, tgtVal: any) => any;
+export type MergeFn = (originValue: any, newValue: any) => any;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d24a06 and cac988e.

📒 Files selected for processing (2)
  • src/utils/set.ts (3 hunks)
  • tests/utils.test.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/utils.test.ts (1)
src/utils/set.ts (1)
  • deepMerge (79-126)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test / react component workflow
🔇 Additional comments (2)
tests/utils.test.ts (1)

3-3: LGTM!

导入 deepMerge 与现有的 setmerge 一起导入,符合新增功能的测试需求。

src/utils/set.ts (1)

79-126: LGTM!

deepMerge 实现逻辑正确:

  • 默认 prepareArray 返回空数组,保持与原 merge 行为一致
  • 循环引用检测通过 loopSet 正确处理
  • 支持自定义数组合并策略,满足 PR 目标中 Form.List 的需求

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/utils/set.ts (1)

128-133: 补全 merge 的 JSDoc 并显式声明返回类型

merge 的注释目前被截断为 “Merge objects which will create”,语义不完整,也没有参数 / 返回值说明。这一点和之前的 review 反馈是一致的。

可以顺便把返回类型显式标出来,便于 IDE 和文档生成:

-/**
- * Merge objects which will create
- */
-export function merge<T extends object>(...sources: T[]) {
-  return deepMerge(sources);
-}
+/**
+ * Wrapper around {@link deepMerge} using the default array strategy.
+ * 默认情况下,数组会被后面的源对象覆盖。
+ *
+ * @param sources 要从左到右合并的对象列表。
+ * @returns 新的合并结果对象,不修改任何源对象。
+ */
+export function merge<T extends object>(...sources: T[]): T {
+  return deepMerge(sources);
+}
🧹 Nitpick comments (2)
src/utils/set.ts (2)

69-87: 补充 deepMerge 的 JSDoc 说明 prepareArray 语义

MergeFnconfig.prepareArray 已经支持自定义数组策略,但 JSDoc 目前只说明了“默认返回空数组会覆盖后面的数组”,没有明确回调参数 current / next 的含义,也没有标注返回值信息;对使用者来说不够直观。

建议在 JSDoc 中补充参数和返回值说明,大致如下(文案可按项目惯例微调):

-/**
- * Merge multiple objects. Support custom merge logic.
- * @param sources object sources
- * @param config.prepareArray Customize array prepare function.
- * It will return empty [] by default.
- * So when match array, it will auto be override with next array in sources.
- */
+/**
+ * Deep merge multiple objects. Support custom merge logic.
+ *
+ * @param sources 对象源数组,从左到右依次合并。
+ * @param config  可选的合并配置。
+ * @param config.prepareArray
+ *   自定义数组容器的准备逻辑。
+ *   参数 `current` 为当前结果中的旧值(可能为 `undefined`),
+ *   `next` 为当前源对象上的数组值。
+ *   默认实现始终返回新的空数组 `[]`,因此数组会被后面的源对象覆盖。
+ * @returns 一个新的已合并对象,不会修改输入对象。
+ */
 export function deepMerge<T extends object>(
   sources: T[],
   config: {
     prepareArray?: MergeFn;
   } = {},
 ) {
   const { prepareArray } = config;
   const finalPrepareArray: MergeFn = prepareArray || (() => []);

105-107: 更新数组分支注释以反映可自定义行为

这里已经通过 finalPrepareArray(originValue, value) 支持自定义数组策略,// Array will always be override 注释只描述了默认行为,容易误导阅读者。

建议改成更准确的说明,例如:

-          if (isArr) {
-            // Array will always be override
-            clone = set(clone, path, finalPrepareArray(originValue, value));
+          if (isArr) {
+            // Array container is prepared via `prepareArray` (default: override).
+            clone = set(clone, path, finalPrepareArray(originValue, value));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cac988e and 67bfef8.

📒 Files selected for processing (1)
  • src/utils/set.ts (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test / react component workflow

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/utils/set.ts (1)

128-134: LGTM!

JSDoc 已完善,清晰说明了函数行为和数组默认替换语义。保持了向后兼容性的同时委托给 deepMerge 实现。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e968fa and ce49d32.

📒 Files selected for processing (1)
  • src/utils/set.ts (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test / react component workflow
  • GitHub Check: test / react component workflow
🔇 Additional comments (2)
src/utils/set.ts (2)

69-71: LGTM!

MergeFn 类型的参数命名 currentnext 清晰明了,与 line 107 的调用 finalPrepareArray(originValue, value) 语义一致。


105-107: LGTM!

数组合并逻辑正确,finalPrepareArray(originValue, value) 的调用顺序与 MergeFn 类型签名一致,默认行为(返回空数组)确保数组被后续源覆盖。

@zombieJ zombieJ changed the title feat: support deep merge feat: support custom merge Dec 8, 2025
@zombieJ zombieJ merged commit f888cf3 into master Dec 8, 2025
12 checks passed
@zombieJ zombieJ deleted the deepMerge branch December 8, 2025 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants