You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ast-grep实现ESLint的prefer-object-spread规则?

解决ast-grep中prefer-object-spread规则的嵌套参数匹配问题

问题背景

我正在对比不同代码检查器(linter)的自定义规则性能:ast-grep基于Rust开发,性能优于ESLint,但ESLint拥有大量成熟规则,ast-grep的规则数量相对较少。为此我尝试实现ESLint的经典规则prefer-object-spread,目标是将:

Object.assign({}, defaultConfig, customizedConfig)

转换为:

{...defaultConfig, ...customizedConfig}

遇到的问题

当前实现存在参数匹配错误:匹配Object.assign的顶层参数时,会错误匹配参数的子节点。例如:

  • 输入Object.assign({}, defaultConfigGenerator(16)),会被错误转换为{...defaultConfigGenerator(16), ...16}
  • 输入Object.assign({}, Object.assign(a,b)),会错误展开内层Object.assign的参数,而非保留整个调用表达式作为单个展开项

问题根源是处理剩余参数$$$REMAINING_ARGS时,传入重写器的内容包含了子节点,且重写器内的元变量与主规则无关联,无法限制仅匹配arguments节点的直接子节点。

解决方案

修正ast-grep规则,通过精确匹配arguments的直接子节点,避免递归匹配子节点内容。以下是修正后的完整规则:

id: prefer_object_spread
language: javascript

rule:
  pattern: Object.assign($FIRST_ARG_OBJ_LITERAL, $$$REMAINING_ARGS)
  has:
    kind: object
    stopBy: end
    pattern: $FIRST_ARG_OBJ_LITERAL
  # 关键:限制$$$REMAINING_ARGS仅匹配arguments的直接子节点,不递归
  inside:
    kind: arguments

rewriters:
- id: argument_spreader
  rule:
    # 匹配单个参数节点,而非递归匹配子内容
    pattern: $ARG
  fix: "...$ARG"

transform:
  ORIGINAL_FIRST_OBJ:
    rewrite:
      rewriters: [] # 移除第一个空对象字面量的处理
      source: $FIRST_ARG_OBJ_LITERAL
  SPREAD_REMAINDERS:
    rewrite:
      rewriters: [argument_spreader]
      source: $$$REMAINING_ARGS
      joinBy: ","

fix: "{${SPREAD_REMAINDERS}}"

测试案例验证

修正后的规则可以正确处理以下场景:

  1. 基础场景:
    // 输入
    Object.assign({}, abc, bde)
    // 输出
    {...abc, ...bde}
    
  2. 参数为函数调用:
    // 输入
    Object.assign({}, defaultConfigGenerator(16))
    // 输出
    {...defaultConfigGenerator(16)}
    
  3. 嵌套Object.assign:
    // 输入
    Object.assign({}, Object.assign(a,b))
    // 输出
    {...Object.assign(a,b)}
    
  4. 多参数混合:
    // 输入
    Object.assign({}, {a:1}, {abc:"Def"}, a, b, c)
    // 输出
    {...{a:1}, ...{abc:"Def"}, ...a, ...b, ...c}
    

内容的提问来源于stack exchange,提问作者Steven Love

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:13:11