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

如何在clang-tidy中从cxxNewExpr获取类型以替换new表达式

用Clang-Tidy替换new T(...)为New<T>(...)的正确实现

你的问题出在直接绑定了整个CXXNewExpr节点,导致把完整的new表达式当成模板参数。要解决这个问题,必须拆解CXXNewExpr的核心组成部分:分配类型和构造参数,再拼接成目标格式。

关键实现步骤

  • 提取分配类型:通过CXXNewExpr::getAllocatedType()获取要实例化的类型,转成字符串作为模板参数。
  • 提取构造参数:通过CXXNewExpr::getConstructorArgs()遍历所有构造参数,提取每个参数的源码文本并拼接成参数列表。
  • 生成替换内容:将类型和参数拼接成New<Type>(Args)的格式,替换原有的new表达式。

完整的Clang-Tidy Check示例代码

#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Lex/Lexer.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;

class NewToNewTemplateCallback : public MatchFinder::MatchCallback {
public:
  void run(const MatchFinder::MatchResult &Result) override {
    const auto *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>("newExpr");
    if (!NewExpr || NewExpr->isArray()) { // 跳过数组形式的new[]
      return;
    }

    // 获取分配类型的字符串
    QualType AllocType = NewExpr->getAllocatedType();
    std::string TypeStr = AllocType.getAsString();

    // 拼接构造参数
    std::string ArgsStr;
    for (unsigned i = 0; i < NewExpr->getNumConstructorArgs(); ++i) {
      const Expr *Arg = NewExpr->getConstructorArg(i);
      if (i != 0) {
        ArgsStr += ", ";
      }
      // 提取参数的源码文本
      ArgsStr += Lexer::getSourceText(
          CharSourceRange::getTokenRange(Arg->getSourceRange()),
          *Result.SourceManager,
          Result.Context->getLangOpts());
    }

    // 生成替换字符串
    std::string Replacement = "New<" + TypeStr + ">(" + ArgsStr + ")";

    // 执行替换
    auto &Replaces = *Result.Context->get<Replacements>();
    (void)Replaces.add(
        Replacement(*Result.SourceManager, NewExpr->getSourceRange()),
        Replacement);
  }
};

// 注册Matcher
void RegisterMatchers(MatchFinder &Finder) {
  Finder.addMatcher(cxxNewExpr().bind("newExpr"),
                    new NewToNewTemplateCallback());
}

注意事项

  • 代码中加入了NewExpr->isArray()判断,避免误替换数组分配的new T[]形式。
  • 如果你的New模板需要处理const、引用等修饰的类型,getAllocatedType()会自动保留这些修饰符,无需额外处理。
  • 对于复杂构造参数(比如带运算符、函数调用的参数),Lexer::getSourceText会完整保留原始源码格式,确保替换后的参数逻辑不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:41:18