[ruby/prism] Various cleanup for initializers and typechecks

https://github.com/ruby/prism/commit/86cf82794a
This commit is contained in:
Kevin Newton 2024-07-03 11:23:17 -04:00
parent 2bf9ae3fa1
commit aa473489a2
8 changed files with 66 additions and 38 deletions

View File

@ -588,6 +588,7 @@ module Prism
autoload :Newlines, "prism/parse_result/newlines" autoload :Newlines, "prism/parse_result/newlines"
private_constant :Comments private_constant :Comments
private_constant :Errors
private_constant :Newlines private_constant :Newlines
# The syntax tree that was parsed from the source code. # The syntax tree that was parsed from the source code.

View File

@ -32,19 +32,19 @@ module Prism
io = StringIO.new io = StringIO.new
source_lines.each.with_index(1) do |line, line_number| source_lines.each.with_index(1) do |line, line_number|
io.puts(line) io.puts(line)
(error_lines.delete(line_number) || []).each do |error| (error_lines.delete(line_number) || []).each do |error|
location = error.location location = error.location
case line_number case line_number
when location.start_line when location.start_line
io.print(" " * location.start_column + "^") io.print(" " * location.start_column + "^")
if location.start_line == location.end_line if location.start_line == location.end_line
if location.start_column != location.end_column if location.start_column != location.end_column
io.print("~" * (location.end_column - location.start_column - 1)) io.print("~" * (location.end_column - location.start_column - 1))
end end
io.puts(" " + error.message) io.puts(" " + error.message)
else else
io.puts("~" * (line.bytesize - location.start_column)) io.puts("~" * (line.bytesize - location.start_column))
@ -56,7 +56,7 @@ module Prism
end end
end end
end end
io.puts io.puts
io.string io.string
end end

View File

@ -104,6 +104,7 @@ Gem::Specification.new do |spec|
"prism.gemspec", "prism.gemspec",
"rbi/prism.rbi", "rbi/prism.rbi",
"rbi/prism/compiler.rbi", "rbi/prism/compiler.rbi",
"rbi/prism/dsl.rbi",
"rbi/prism/inspect_visitor.rbi", "rbi/prism/inspect_visitor.rbi",
"rbi/prism/node_ext.rbi", "rbi/prism/node_ext.rbi",
"rbi/prism/node.rbi", "rbi/prism/node.rbi",

View File

@ -69,8 +69,15 @@ module Prism
# Create a new <%= node.name %> node. # Create a new <%= node.name %> node.
def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field| def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field|
case field case field
when Prism::Template::NodeField, Prism::Template::ConstantField when Prism::Template::NodeField
"#{field.name}: default_node(source, location)" if !field.kind?
"#{field.name}: default_node(source, location)"
else
kind = field.specific_kind || field.union_kind.first
"#{field.name}: #{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)"
end
when Prism::Template::ConstantField
"#{field.name}: :\"\""
when Prism::Template::OptionalNodeField, Prism::Template::OptionalConstantField, Prism::Template::OptionalLocationField when Prism::Template::OptionalNodeField, Prism::Template::OptionalConstantField, Prism::Template::OptionalLocationField
"#{field.name}: nil" "#{field.name}: nil"
when Prism::Template::NodeListField, Prism::Template::ConstantListField when Prism::Template::NodeListField, Prism::Template::ConstantListField
@ -79,8 +86,10 @@ module Prism
"#{field.name}: \"\"" "#{field.name}: \"\""
when Prism::Template::LocationField when Prism::Template::LocationField
"#{field.name}: location" "#{field.name}: location"
when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField, Prism::Template::DoubleField when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField
"#{field.name}: 0" "#{field.name}: 0"
when Prism::Template::DoubleField
"#{field.name}: 0.0"
else else
raise raise
end end
@ -96,7 +105,7 @@ module Prism
<%- flag.values.each do |value| -%> <%- flag.values.each do |value| -%>
when :<%= value.name.downcase %> then <%= flag.name %>::<%= value.name %> when :<%= value.name.downcase %> then <%= flag.name %>::<%= value.name %>
<%- end -%> <%- end -%>
else raise ArgumentError, "invalid <%= flag.name %> flag: #{name.inspect}" else Kernel.raise ArgumentError, "invalid <%= flag.name %> flag: #{name.inspect}"
end end
end end
<%- end -%> <%- end -%>
@ -118,7 +127,7 @@ module Prism
# The default node that gets attached to nodes if no node is specified for a # The default node that gets attached to nodes if no node is specified for a
# required node field. # required node field.
def default_node(source, location) def default_node(source, location)
MissingNode.new(source, location) MissingNode.new(source, -1, location, 0)
end end
end end
end end

View File

@ -93,6 +93,10 @@ module Prism
# Some node fields can be specialized if they point to a specific kind of # Some node fields can be specialized if they point to a specific kind of
# node and not just a generic node. # node and not just a generic node.
class NodeKindField < Field class NodeKindField < Field
def kind?
options.key?(:kind)
end
def c_type def c_type
if specific_kind if specific_kind
"pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}" "pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}"
@ -624,6 +628,7 @@ module Prism
"src/prettyprint.c", "src/prettyprint.c",
"src/serialize.c", "src/serialize.c",
"src/token_type.c", "src/token_type.c",
"rbi/prism/dsl.rbi",
"rbi/prism/node.rbi", "rbi/prism/node.rbi",
"rbi/prism/visitor.rbi", "rbi/prism/visitor.rbi",
"sig/prism.rbs", "sig/prism.rbs",

View File

@ -18,6 +18,12 @@ module Prism
] ]
end end
if RUBY_VERSION < "3.4"
filepaths -= [
"it_with_ordinary_parameter.txt"
]
end
filepaths.each do |filepath| filepaths.each do |filepath|
define_method(:"test_#{File.basename(filepath, ".txt")}") do define_method(:"test_#{File.basename(filepath, ".txt")}") do
assert_errors(File.join(base, filepath)) assert_errors(File.join(base, filepath))
@ -77,7 +83,7 @@ module Prism
private private
def assert_errors(filepath) def assert_errors(filepath)
expected = File.read(filepath) expected = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8)
source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "") source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "")
refute_valid_syntax(source) refute_valid_syntax(source)

View File

@ -76,33 +76,38 @@ module Prism
end end
def test_literal_in_conditionals def test_literal_in_conditionals
source = <<~RUBY sources = [
if (a = 2); a; end "if (a = 2); a; end",
if ($a = 2); end "if ($a = 2); end",
if (@a = 2); end "if (@a = 2); end",
if (@@a = 2); end "if a; elsif b = 2; b end",
if a; elsif b = 2; b end "unless (a = 2); a; end",
unless (a = 2); a; end "unless ($a = 2); end",
unless ($a = 2); end "unless (@a = 2); end",
unless (@a = 2); end "while (a = 2); a; end",
unless (@@a = 2); end "while ($a = 2); end",
while (a = 2); a; end "while (@a = 2); end",
while ($a = 2); end "until (a = 2); a; end",
while (@a = 2); end "until ($a = 2); end",
while (@@a = 2); end "until (@a = 2); end",
until (a = 2); a; end "foo if (a, b = 2); [a, b]",
until ($a = 2); end "foo if a = 2 and a",
until (@a = 2); end "(@foo = 1) ? a : b",
until (@@a = 2); end "!(a = 2) and a",
foo if (a, b = 2); [a, b] "not a = 2 and a"
foo if a = 2 and a ]
(@foo = 1) ? a : b
!(a = 2) and a
not a = 2 and a
RUBY
source.each_line(chomp: true) do |line| if RUBY_VERSION >= "3.3"
assert_warning(line, "found '= literal' in conditional, should be ==") sources.push(
"if (@@a = 2); end",
"unless (@@a = 2); end",
"while (@@a = 2); end",
"until (@@a = 2); end"
)
end
sources.each do |source|
assert_warning(source, "= literal' in conditional, should be ==")
end end
end end

View File

@ -2,11 +2,12 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "rubocop", ">= 1.52.1", "< 2" gemspec path: "../.."
gem "minitest" gem "minitest"
gem "rake" gem "rake"
gem "rake-compiler" gem "rake-compiler"
gem "rspec" gem "rspec"
gem "rubocop", ">= 1.52.1", "< 2"
gem "test-unit" gem "test-unit"
gem "rb_sys" gem "rb_sys"