diff --git a/lib/rbs_inline_data/parser.rb b/lib/rbs_inline_data/parser.rb index 4221516..5d31696 100644 --- a/lib/rbs_inline_data/parser.rb +++ b/lib/rbs_inline_data/parser.rb @@ -7,7 +7,7 @@ class Parser < Prism::Visitor # @rbs skip TypedDefinition = Data.define( :class_name, #:: String - :fields #:: Array[TypedField] + :fields #:: Array[RbsInlineData::Parser::TypedField] ) # @rbs skip TypedField = Data.define( @@ -79,14 +79,14 @@ def define_data?(node) #:: (Prism::ConstantWriteNode) -> RbsInlineData::Parser::TypedDefinition? def extract_definition(node) source = node.slice - _, class_name, field_text = source.match(/\A([a-zA-Z]+) = Data\.define\(([\n\s\w\W]+)\)\z/).to_a + _, class_name, field_text = source.match(/\A([a-zA-Z0-9]+) ?= ?Data\.define\(([\n\s\w\W]+)\)\z/).to_a return nil if field_text.nil? || class_name.nil? class_name = "#{@surronding_class_or_module.join("::")}::#{class_name}" fields = field_text.split("\n").map(&:strip).reject(&:empty?).map do |str| case str - when /:(\w+),? #:: ([\w\[\]]+)/ + when /:(\w+),? #:: ([\w\:\[\]]+)/ [::Regexp.last_match(1), ::Regexp.last_match(2)] when /:(\w+),?/ [::Regexp.last_match(1), "untyped"] diff --git a/sig/generated/data/lib/rbs_inline_data/parser.rbs b/sig/generated/data/lib/rbs_inline_data/parser.rbs index 8cb865c..e577d26 100644 --- a/sig/generated/data/lib/rbs_inline_data/parser.rbs +++ b/sig/generated/data/lib/rbs_inline_data/parser.rbs @@ -1,7 +1,7 @@ class RbsInlineData::Parser::TypedDefinition extend Data::_DataClass attr_reader class_name: String - attr_reader fields: Array[TypedField] + attr_reader fields: Array[RbsInlineData::Parser::TypedField] def self.new: (*untyped) -> ::RbsInlineData::Parser::TypedDefinition | (**untyped) -> ::RbsInlineData::Parser::TypedDefinition | ... diff --git a/test/rbs_inline_data/parser_test.rb b/test/rbs_inline_data/parser_test.rb new file mode 100644 index 0000000..2b70a46 --- /dev/null +++ b/test/rbs_inline_data/parser_test.rb @@ -0,0 +1,109 @@ +require "test_helper" +require "rbs_inline_data/parser" + +module RbsInlineData + class ParserTest < Minitest::Test + def parse_ruby(src) + Prism.parse(src) + end + + def test_simple + definitions = Parser.parse(parse_ruby(<<~RUBY)) + class Foo + Bar = Data.define( + :value, #:: String + ) + Bar2=Data.define( + :value, #:: Integer + ) + end + RUBY + + assert_equal definitions[0], Parser::TypedDefinition.new( + class_name: "Foo::Bar", + fields: [ + Parser::TypedField.new(field_name: "value", type: "String"), + ]) + assert_equal definitions[1], Parser::TypedDefinition.new( + class_name: "Foo::Bar2", + fields: [ + Parser::TypedField.new(field_name: "value", type: "Integer"), + ]) + end + + def test_multiple_definition + definitions = Parser.parse(parse_ruby(<<~RUBY)) + class Foo + Bar = Data.define( + :string_value, #:: String + ) + Bar2 = Data.define( + :string_value, #:: String + ) + end + RUBY + + assert_equal definitions[0], Parser::TypedDefinition.new( + class_name: "Foo::Bar", + fields: [ + Parser::TypedField.new(field_name: "string_value", type: "String"), + ]) + assert_equal definitions[1], Parser::TypedDefinition.new( + class_name: "Foo::Bar2", + fields: [ + Parser::TypedField.new(field_name: "string_value", type: "String"), + ]) + end + + def test_untyped + definitions = Parser.parse(parse_ruby(<<~RUBY)) + class Foo + Bar = Data.define( + :value #:: untyped + ) + Bar2 = Data.define( + :value + ) + Bar3 = Data.define(:value) + end + RUBY + + assert_equal definitions[0], Parser::TypedDefinition.new( + class_name: "Foo::Bar", + fields: [ + Parser::TypedField.new(field_name: "value", type: "untyped"), + ]) + assert_equal definitions[1], Parser::TypedDefinition.new( + class_name: "Foo::Bar2", + fields: [ + Parser::TypedField.new(field_name: "value", type: "untyped"), + ]) + assert_equal definitions[2], Parser::TypedDefinition.new( + class_name: "Foo::Bar3", + fields: [ + Parser::TypedField.new(field_name: "value", type: "untyped"), + ]) + end + + def test_nested_type + definitions = Parser.parse(parse_ruby(<<~RUBY)) + class A + class B + class C; end + D = Data.define( + :x, #:: A::B::C + :y #:: Array[A::B::C] + ) + end + end + RUBY + + assert_equal definitions[0], Parser::TypedDefinition.new( + class_name: "A::B::D", + fields: [ + Parser::TypedField.new(field_name: "x", type: "A::B::C"), + Parser::TypedField.new(field_name: "y", type: "Array[A::B::C]"), + ]) + end + end +end diff --git a/test/test_rbs_inline_data.rb b/test/test_rbs_inline_data.rb deleted file mode 100644 index 5dd4084..0000000 --- a/test/test_rbs_inline_data.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -require "test_helper" - -class TestRbsInlineData < Minitest::Test - def test_that_it_has_a_version_number - refute_nil ::RbsInlineData::VERSION - end - - def test_it_does_something_useful - assert false - end -end