Repository: onnx/onnx
File: onnx/inliner/inliner.cc (C++)

Code before:
      : generator_(std::make_unique<NameGenerator>(function)), suffix_("__" + prefix) {}

  std::string CreateUnique(const std::string& name) {
    return generator_->CreateNew(name + suffix_);
  }

  void BindName(const std::string& formal_name, const std::string& actual_name) {
    name_bindings_[formal_name] = actual_name;
  }

  std::string LookupOrCreate(const std::string& name, bool is_new_def) {
    // First check if we have a binding for this name
    auto it = name_bindings_.find(name);
    if (it != name_bindings_.end()) {
      return it->second;
    }

    // If it's a new definition and not bound, create a unique name
    if (is_new_def) {
      std::string new_name = CreateUnique(name);
      name_bindings_[name] = new_name;
      return new_name;
    }

    // Otherwise, leave the name unchanged (outer scope variable)
    return name;
  }

  void RenameNode(NodeProto& node) {
    // Rename node name if it exists
    if (!node.name().empty()) {
      node.set_name(CreateUnique(node.name()));
    }

    // Rename inputs (these are references, not new definitions)
    for (int i = 0; i < node.input_size(); ++i) {
      std::string& input_name = *node.mutable_input(i);
      if (!input_name.empty()) {
        input_name = LookupOrCreate(input_name, false);
      }
    }

    // Rename outputs (these are new definitions)
    for (int i = 0; i < node.output_size(); ++i) {
      std::string& output_name = *node.mutable_output(i);
      if (!output_name.empty()) {
        output_name = LookupOrCreate(output_name, true);
      }
    }
  }
};

Review comment (suggestion):
Can you use the class InlinerRenamer (via inheritance or delegation) to do most of the work? One important reason is that renamer will need to iterate through graph-value attributes in a node, which will need recursive traversal through nodes in that subgraph, etc. which are already handled there.

Code after:
}

void InlineLocalFunctions(ModelProto& model, bool convert_version) {
  InlinerImpl::InlineLocalFunctions(model, convert_version);
}

void InlineSelectedLocalFunctions(ModelProto& model, const FunctionIdSet& to_inline) {
  InlinerImpl::InlineSelectedLocalFunctions(model, to_inline);
}

void InlineSelectedFunctions(ModelProto& model, const FunctionIdSet& to_inline) {
  InlineSelectedLocalFunctions(model, to_inline);
}

void InlineSelectedFunctions(
    ModelProto& model,
    const FunctionIdSet& to_inline,
    const ISchemaRegistry* schema_registry) {
  if (schema_registry == nullptr) {
    schema_registry = OpSchemaRegistry::Instance();
  }
  InlinerImpl::InlineSelectedFunctions(model, to_inline, schema_registry);
}

// Implementation of the Renamer class using InliningRenamer directly
class Renamer::Impl {
 private:
  NameGenerator generator_;
  InliningRenamer renamer_;

 public:
  Impl(const std::string& prefix, const GraphProto& graph) : generator_(graph), renamer_("__" + prefix, generator_) {}

  Impl(const std::string& prefix, const FunctionProto& function)
      : generator_(function), renamer_("__" + prefix, generator_) {}

  InliningRenamer& GetRenamer() {
    return renamer_;
  }

  void BindName(const std::string& formal_name, const std::string& actual_name) {
    renamer_.BindFormalToActual(formal_name, actual_name);
  }

  void RenameNode(NodeProto& node) {
    // Use the InliningRenamer's ProcessNode method which handles graph-value attributes
    renamer_.ProcessNode(&node);
  }
};

Renamer::Renamer(const std::string& prefix, const GraphProto& graph) : pImpl_(std::make_unique<Impl>(prefix, graph)) {}