[ruby/prism] Introduce field comments

In an effort to further improve our documentation, this commit
introduces the concept of templating comments onto fields. I hope
to get more documentation above the nuances of specific fields this
way going forward.

With this, we template the comments into C and Ruby. I haven't done
JS or Java yet, but we can touch those in the future, especially
once their documentation is published.

https://github.com/ruby/prism/commit/af300d5fb3
This commit is contained in:
Kevin Newton 2024-01-02 15:26:21 -05:00 committed by git
parent adbfbd822f
commit e46922e48f
4 changed files with 37 additions and 7 deletions

View File

@ -714,6 +714,19 @@ nodes:
kind: CallNodeFlags kind: CallNodeFlags
- name: receiver - name: receiver
type: node? type: node?
comment: |
The object that the method is being called on. This can be either
`nil` or a node representing any kind of expression that returns a
non-void value.
foo.bar
^^^
+foo
^^^
foo + bar
^^^
- name: call_operator_loc - name: call_operator_loc
type: location? type: location?
- name: name - name: name

View File

@ -165,7 +165,9 @@ typedef struct pm_<%= node.human %> {
pm_node_t base; pm_node_t base;
<%- node.fields.grep_v(Prism::FlagsField).each do |field| -%> <%- node.fields.grep_v(Prism::FlagsField).each do |field| -%>
/** <%= node.name %>#<%= field.name %> */ /**
* <%= node.name %>#<%= field.name %><%= "\n *\n * " + field.comment.split("\n").join("\n * ") if field.comment %>
*/
<%= case field <%= case field
when Prism::NodeField, Prism::OptionalNodeField then "struct #{field.c_type} *#{field.name}" when Prism::NodeField, Prism::OptionalNodeField then "struct #{field.c_type} *#{field.name}"
when Prism::NodeListField then "struct pm_node_list #{field.name}" when Prism::NodeListField then "struct pm_node_list #{field.name}"

View File

@ -44,7 +44,11 @@ module Prism
<%- end -%> <%- end -%>
class <%= node.name -%> < Node class <%= node.name -%> < Node
<%- node.fields.each do |field| -%> <%- node.fields.each do |field| -%>
<%- if field.comment.nil? -%>
# <%= "private " if field.is_a?(Prism::FlagsField) %>attr_reader <%= field.name %>: <%= field.rbs_class %> # <%= "private " if field.is_a?(Prism::FlagsField) %>attr_reader <%= field.name %>: <%= field.rbs_class %>
<%- else -%>
# <%= field.comment.split("\n").join("\n # ") %>
<%- end -%>
<%= "private " if field.is_a?(Prism::FlagsField) %>attr_reader :<%= field.name %> <%= "private " if field.is_a?(Prism::FlagsField) %>attr_reader :<%= field.name %>
<%- end -%> <%- end -%>

View File

@ -13,10 +13,12 @@ module Prism
# This represents a field on a node. It contains all of the necessary # This represents a field on a node. It contains all of the necessary
# information to template out the code for that field. # information to template out the code for that field.
class Field class Field
attr_reader :name, :options attr_reader :name, :comment, :options
def initialize(name:, type:, **options) def initialize(name:, comment: nil, **options)
@name, @type, @options = name, type, options @name = name
@comment = comment
@options = options
end end
def semantic_field? def semantic_field?
@ -248,8 +250,8 @@ module Prism
end end
end end
# This class represents a node in the tree, configured by the config.yml file in # This class represents a node in the tree, configured by the config.yml file
# YAML format. It contains information about the name of the node and the # in YAML format. It contains information about the name of the node and the
# various child nodes it contains. # various child nodes it contains.
class NodeType class NodeType
attr_reader :name, :type, :human, :fields, :newline, :comment attr_reader :name, :type, :human, :fields, :newline, :comment
@ -263,7 +265,16 @@ module Prism
@fields = @fields =
config.fetch("fields", []).map do |field| config.fetch("fields", []).map do |field|
field_type_for(field.fetch("type")).new(**field.transform_keys(&:to_sym)) type = field_type_for(field.fetch("type"))
options = field.transform_keys(&:to_sym)
options.delete(:type)
# If/when we have documentation on every field, this should be changed
# to use fetch instead of delete.
comment = options.delete(:comment)
type.new(comment: comment, **options)
end end
@newline = config.fetch("newline", true) @newline = config.fetch("newline", true)