mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Partial fix for #21092 .
This adds a number of Ruby files to the `lib/docs` directory. These files are not actually required by the Protobuf gem, so they should not affect any functionality. They are only there to key off of the auto-generation by [https://www.rubydoc.info](https://www.rubydoc.info) .
For now I've left the comments in the C and Java code. However, they duplicate what I have there (since I largely copy/pasted the English content from those comments). One thing we could do is change the comments to reference the Ruby files, e.g.:
```c
/*
* See documentation: ../../../lib/stubs/descriptor_pool#lookup
*/
static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
```
I can make those changes if approved.
This PR does *not* include files generated by Protobuf from `.proto` files. That means that references to things like `ServiceDescriptorProto` don't go anywhere. I can look at generating similar files to this via a protoc plugin, although it'd be a bit in-depth. Or I could do it by hand of course :)
Note that the [current rubydocs](https://www.rubydoc.info/gems/google-protobuf) does have some entries, but they are mostly from the FFI implementation and are kind of an "accident". My PR specifies the files to generate should *only* come from the `lib/docs` folder.
Feedback welcome!
Closes #21212
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/21212 from dorner:ruby-doc 9cc3613339
PiperOrigin-RevId: 768309166
95 lines
3.1 KiB
Ruby
95 lines
3.1 KiB
Ruby
# This script parses the comments in the Ruby C extension files and translates them into Ruby
|
|
# stubs. It looks for an instance of `ruby-doc:` and takes the following string as the object
|
|
# under documentation (a class, instance method, or class method).
|
|
# The intention of generating these files is for use by YARD to auto-generate documentation
|
|
# here: https://www.rubydoc.info/gems/google-protobuf/
|
|
#
|
|
# Because these comments are essentially "pretending" to be Ruby, we had to add one additional
|
|
# YARD tag, `@paramdefault`, which is not a standard YARD tag. This tag is used to specify default
|
|
# values for parameters.
|
|
|
|
require 'erb'
|
|
|
|
files = Dir.glob('ext/**/*.c')
|
|
classes = {}
|
|
MethodDefn = Struct.new(:name, :body, keyword_init: true) do
|
|
def params
|
|
params = body.scan(/@param (\S+) /).map { |p| p[0]}
|
|
defaults = body.scan(/@paramdefault (\S+) (\S+)/).map { |p| [p[0], p[1]]}.to_h
|
|
params = params.map { |p| p == 'kwargs' ? '**kwargs' : p }
|
|
params = params.map { |p| defaults[p] ? "#{p}=#{defaults[p]}" : p }
|
|
if body.include?('@yield')
|
|
params.push('&block')
|
|
end
|
|
params
|
|
end
|
|
end
|
|
|
|
Defn = Struct.new(:name, :instance_meths, :class_meths, :body) do
|
|
def initialize(*args, **kwargs)
|
|
super
|
|
self.instance_meths ||= []
|
|
self.class_meths ||= []
|
|
end
|
|
end
|
|
|
|
files.each do |file|
|
|
defs = File.read(file).scan(/ruby-doc:(.*?)\n(.*?)\*\//m)
|
|
defs.each do |definition|
|
|
name = definition[0].strip
|
|
body = definition[1].strip.
|
|
gsub(/^\s*\*/, '').
|
|
gsub(/\n/m, "\n # ").strip
|
|
if name.include?('.')
|
|
klass, method_name = name.split('.')
|
|
method = MethodDefn.new(name: method_name, body: body)
|
|
classes[klass] ||= Defn.new(name: klass)
|
|
classes[klass].class_meths.push(method)
|
|
elsif name.include?('#')
|
|
klass, method_name = name.split('#')
|
|
method = MethodDefn.new(name: method_name, body: body)
|
|
classes[klass] ||= Defn.new(name: klass)
|
|
classes[klass].instance_meths.push(method)
|
|
else
|
|
classes[name] = Defn.new(name: name, body: body)
|
|
end
|
|
end
|
|
end
|
|
|
|
# copied from ActiveSupport::Inflector
|
|
def underscore(str)
|
|
regex = /(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/
|
|
str.gsub(regex) { "#{$1 && '_' }#{$2.downcase}" }.
|
|
gsub(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }.
|
|
downcase
|
|
end
|
|
|
|
class_erb = <<-ERB
|
|
# This file was generated by generate_stubs.rb
|
|
# Do not edit this file directly.
|
|
|
|
<%- if defn.body -%>
|
|
<%= defn.body.gsub(' #', '#').gsub('# ', '# ') %>
|
|
<%- end -%>
|
|
class Google::Protobuf::<%= name %>
|
|
<%- defn.instance_meths.each do |meth| -%>
|
|
|
|
<%= meth.body.gsub('# ', '# ') %>
|
|
def <%= meth.name %><% if meth.params.any? %>(<%= meth.params.join(', ') %>)<% end %>; end
|
|
<%- end -%>
|
|
<%- defn.class_meths.each do |meth| -%>
|
|
|
|
<%= meth.body.gsub('# ', '# ') %>
|
|
def self.<%= meth.name %><% if meth.params.any? %>(<%= meth.params.join(', ') %>)<% end %>; end
|
|
<%- end -%>
|
|
|
|
end # class Google::Protobuf::<%= name %>
|
|
ERB
|
|
|
|
classes.each do |name, defn|
|
|
file = File.join('lib/stubs', "#{underscore(name)}.rb")
|
|
File.open(file, 'w') do |f|
|
|
result = ERB.new(class_erb, trim_mode: '-').result(binding)
|
|
f.puts result
|
|
end
|
|
end
|