diff --git a/prism/config.yml b/prism/config.yml index 9cf9cf596e..d714d6d698 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -714,6 +714,19 @@ nodes: kind: CallNodeFlags - name: receiver 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 type: location? - name: name diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb index c169fedf0a..3f71b923b7 100644 --- a/prism/templates/include/prism/ast.h.erb +++ b/prism/templates/include/prism/ast.h.erb @@ -165,7 +165,9 @@ typedef struct pm_<%= node.human %> { pm_node_t base; <%- 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 when Prism::NodeField, Prism::OptionalNodeField then "struct #{field.c_type} *#{field.name}" when Prism::NodeListField then "struct pm_node_list #{field.name}" diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 65a4f0fb70..54e48ffccb 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -44,7 +44,11 @@ module Prism <%- end -%> class <%= node.name -%> < Node <%- node.fields.each do |field| -%> + <%- if field.comment.nil? -%> # <%= "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 %> <%- end -%> diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 8cbcf27d79..01d0711148 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -13,10 +13,12 @@ module Prism # This represents a field on a node. It contains all of the necessary # information to template out the code for that field. class Field - attr_reader :name, :options + attr_reader :name, :comment, :options - def initialize(name:, type:, **options) - @name, @type, @options = name, type, options + def initialize(name:, comment: nil, **options) + @name = name + @comment = comment + @options = options end def semantic_field? @@ -248,8 +250,8 @@ module Prism end end - # This class represents a node in the tree, configured by the config.yml file in - # YAML format. It contains information about the name of the node and the + # This class represents a node in the tree, configured by the config.yml file + # in YAML format. It contains information about the name of the node and the # various child nodes it contains. class NodeType attr_reader :name, :type, :human, :fields, :newline, :comment @@ -263,7 +265,16 @@ module Prism @fields = 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 @newline = config.fetch("newline", true)