Skip to content

Commit

Permalink
Merge pull request #8 from euglena1215/support-nested-array
Browse files Browse the repository at this point in the history
Support nested array and nested hash
  • Loading branch information
euglena1215 authored Jan 7, 2024
2 parents 8c387be + 8b64fcc commit d3b945d
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Add packwerk to dependencies https://github.com/euglena1215/packwerk-yard/pull/6
- Introduce sorbet https://github.com/euglena1215/packwerk-yard/pull/7
- Support nested array & nested hash https://github.com/euglena1215/packwerk-yard/pull/8

## [0.1.0] - 2024-01-07

Expand Down
14 changes: 10 additions & 4 deletions lib/packwerk_yard/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ class Parser
include Packwerk::FileParser

# Array Syntax e.g. Array<String>
ARRAY_REGEXP = T.let(/Array<(.+)>/.freeze, Regexp)
ARRAY_REGEXP = T.let(/\AArray<(.+)>/.freeze, Regexp)
private_constant :ARRAY_REGEXP

# Hash Syntax e.g. Hash<String, String>
HASH_REGEXP = T.let(/\AHash<([^,]*),\s?(.*)>/.freeze, Regexp)
private_constant :HASH_REGEXP

sig { params(ruby_parser: T.nilable(Packwerk::Parsers::Ruby)).void }
def initialize(ruby_parser: Packwerk::Parsers::Ruby.new)
@ruby_parser = ruby_parser
Expand All @@ -23,7 +27,7 @@ def call(io:, file_path: "<unknown>")
types = extract_from_yard_to_types(source_code)

to_ruby_ast(
types.map { |type| to_evaluable_type(type) }
types.map { |type| to_evaluable_type(type) }.flatten
.reject { |type| to_constant(type).nil? }
.inspect.delete('"'),
file_path,
Expand Down Expand Up @@ -56,9 +60,11 @@ def extract_from_yard_to_types(source_code)
types.uniq
end

sig { params(type: String).returns(String) }
sig { params(type: String).returns(T::Array[String]) }
def to_evaluable_type(type)
ARRAY_REGEXP.match(type).to_a[1] || type
matched_types = Array(ARRAY_REGEXP.match(type).to_a[1])
matched_types = Array(HASH_REGEXP.match(type).to_a[1..2]) if matched_types.empty?
matched_types.empty? ? [type] : matched_types.map { |t| to_evaluable_type(t) }.flatten
end

sig { params(name: T.any(Symbol, String)).returns(T.untyped) }
Expand Down
9 changes: 9 additions & 0 deletions test/fixtures/yard/nested_array.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class NestedArray
# @param [Array<Array<String>>] array
# @return [Array<Array<String>>]
def nested_array_method(array)
array
end
end
9 changes: 9 additions & 0 deletions test/fixtures/yard/nested_hash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class NestedHash
# @param [Hash<Integer, Hash<Integer, String>>] hash
# @return [Hash<Integer, Hash<Integer, String>>]
def nested_hash(hash)
hash
end
end
21 changes: 21 additions & 0 deletions test/unit/packwerk_yard/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,26 @@ def test_call_return_node_with_not_exists_class_args_file
assert(node.type, :array)
assert(node.children.size, 0)
end

def test_call_return_node_with_nested_array_file
parser = ::PackwerkYard::Parser.new
io = StringIO.new(File.read("test/fixtures/yard/nested_array.rb"))
node = parser.call(io: io, file_path: "test/fixtures/yard/nested_array.rb")

assert_instance_of(::Parser::AST::Node, node)
assert(node.type, :array)
assert(node.children[0].children[1], :String)
end

def test_call_return_node_with_nested_hash_file
parser = ::PackwerkYard::Parser.new
io = StringIO.new(File.read("test/fixtures/yard/nested_hash.rb"))
node = parser.call(io: io, file_path: "test/fixtures/yard/nested_hash.rb")

assert_instance_of(::Parser::AST::Node, node)
assert(node.type, :array)
assert(node.children[0].children[1], :String)
assert(node.children[1].children[1], :Integer)
end
end
end

0 comments on commit d3b945d

Please sign in to comment.