Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Linter

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
clippy:
name: Clippy
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: |
core -> target

- name: Run Clippy
run: cd core && cargo clippy --lib --all-features -- -W clippy::all

rubocop:
name: RuboCop
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
bundler-cache: true

- name: Run RuboCop
run: bundle exec rubocop
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,10 @@ Metrics/MethodLength:

Metrics/AbcSize:
Max: 25

Metrics/ClassLength:
Exclude:
- "test/**/*_test.rb"

Metrics/CyclomaticComplexity:
Max: 10
6 changes: 2 additions & 4 deletions core/src/rbs/method_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,9 @@ def extract_block_param_types(method_type)
block_func = method_type.block.type
return nil unless block_func.is_a?(::RBS::Types::Function)

param_types = []

# Required positional parameters
block_func.required_positionals.each do |param|
param_types << param.type.to_s
param_types = block_func.required_positionals.map do |param|
param.type.to_s
end

# Optional positional parameters
Expand Down
8 changes: 4 additions & 4 deletions test/array_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ class ArrayTest < Minitest::Test
# ============================================

def test_nested_array_integer
assert_type "x = [[1, 2], [3]]", "x", "Array[Array[Integer]]"
assert_type 'x = [[1, 2], [3]]', 'x', 'Array[Array[Integer]]'
end

def test_deeply_nested_array
assert_type "x = [[[1]]]", "x", "Array[Array[Array[Integer]]]"
assert_type 'x = [[[1]]]', 'x', 'Array[Array[Array[Integer]]]'
end

def test_nested_array_mixed
types = infer('x = [[1], ["a"]]')
assert_includes(
["Array[Array[Integer] | Array[String]]", "Array[Array[String] | Array[Integer]]"],
types["x"]
['Array[Array[Integer] | Array[String]]', 'Array[Array[String] | Array[Integer]]'],
types['x']
)
end

Expand Down
54 changes: 27 additions & 27 deletions test/conditional_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ def test_if_else_union_type
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "Integer"
assert_includes type_str, "String"
type_str = types['x']
assert_includes type_str, 'Integer'
assert_includes type_str, 'String'
end

def test_if_without_else_includes_nil
Expand All @@ -32,9 +32,9 @@ def test_if_without_else_includes_nil
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "nil"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'nil'
end

def test_if_elsif_else_union
Expand All @@ -49,10 +49,10 @@ def test_if_elsif_else_union
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "Integer"
assert_includes type_str, "Symbol"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'Integer'
assert_includes type_str, 'Symbol'
end

def test_unless_else_union_type
Expand All @@ -65,9 +65,9 @@ def test_unless_else_union_type
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "Integer"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'Integer'
end

def test_unless_without_else_includes_nil
Expand All @@ -78,9 +78,9 @@ def test_unless_without_else_includes_nil
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "nil"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'nil'
end

def test_case_when_else_union
Expand All @@ -96,10 +96,10 @@ def test_case_when_else_union
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "Integer"
assert_includes type_str, "Symbol"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'Integer'
assert_includes type_str, 'Symbol'
end

def test_case_without_else_includes_nil
Expand All @@ -111,9 +111,9 @@ def test_case_without_else_includes_nil
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "String"
assert_includes type_str, "nil"
type_str = types['x']
assert_includes type_str, 'String'
assert_includes type_str, 'nil'
end

def test_same_type_branches
Expand All @@ -125,7 +125,7 @@ def test_same_type_branches
end
RUBY

assert_type source, "x", "String"
assert_type source, 'x', 'String'
end

# ============================================
Expand Down Expand Up @@ -226,15 +226,15 @@ def test_ternary_union_type
RUBY

types = infer(source)
assert_equal "(Integer | String)", types["x"]
assert_equal '(Integer | String)', types['x']
end

def test_ternary_same_type
source = <<~RUBY
x = true ? "hello" : "world"
RUBY

assert_type source, "x", "String"
assert_type source, 'x', 'String'
end

def test_ternary_nil_branch
Expand All @@ -243,7 +243,7 @@ def test_ternary_nil_branch
RUBY

types = infer(source)
assert_equal "(String | nil)", types["x"]
assert_equal '(String | nil)', types['x']
end

# ============================================
Expand Down
34 changes: 17 additions & 17 deletions test/exception_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ def test_begin_rescue_union_type
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "Integer"
assert_includes type_str, "String"
type_str = types['x']
assert_includes type_str, 'Integer'
assert_includes type_str, 'String'
end

def test_begin_rescue_else_excludes_begin_body
Expand All @@ -36,10 +36,10 @@ def test_begin_rescue_else_excludes_begin_body
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "Symbol"
assert_includes type_str, "Integer"
refute_includes type_str, "String"
type_str = types['x']
assert_includes type_str, 'Symbol'
assert_includes type_str, 'Integer'
refute_includes type_str, 'String'
end

def test_rescue_variable_typed_as_specific_exception
Expand All @@ -52,8 +52,8 @@ def test_rescue_variable_typed_as_specific_exception
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "ArgumentError"
type_str = types['x']
assert_includes type_str, 'ArgumentError'
end

def test_rescue_variable_typed_as_union_of_exceptions
Expand All @@ -66,9 +66,9 @@ def test_rescue_variable_typed_as_union_of_exceptions
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "TypeError"
assert_includes type_str, "NameError"
type_str = types['x']
assert_includes type_str, 'TypeError'
assert_includes type_str, 'NameError'
end

def test_rescue_without_exception_class_defaults_to_standard_error
Expand All @@ -81,8 +81,8 @@ def test_rescue_without_exception_class_defaults_to_standard_error
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "StandardError"
type_str = types['x']
assert_includes type_str, 'StandardError'
end

def test_rescue_modifier_union_type
Expand All @@ -91,9 +91,9 @@ def test_rescue_modifier_union_type
RUBY

types = infer(source)
type_str = types["x"]
assert_includes type_str, "Integer"
assert_includes type_str, "String"
type_str = types['x']
assert_includes type_str, 'Integer'
assert_includes type_str, 'String'
end

# ============================================
Expand Down
8 changes: 4 additions & 4 deletions test/float_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ class FloatTest < Minitest::Test
# ============================================

def test_float_literal
assert_type "x = 3.14", "x", "Float"
assert_type 'x = 3.14', 'x', 'Float'
end

def test_float_ceil_returns_integer
types = infer("x = 3.14\na = x.ceil")
assert_equal "Integer", types["a"]
assert_equal 'Integer', types['a']
end

def test_float_floor_returns_integer
types = infer("x = 3.14\nb = x.floor")
assert_equal "Integer", types["b"]
assert_equal 'Integer', types['b']
end

def test_float_abs_returns_float
types = infer("x = 3.14\nc = x.abs")
assert_equal "Float", types["c"]
assert_equal 'Float', types['c']
end

# ============================================
Expand Down
12 changes: 6 additions & 6 deletions test/hash_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ class HashTest < Minitest::Test
# ============================================

def test_hash_symbol_integer
assert_type "x = { a: 1, b: 2 }", "x", "Hash[Symbol, Integer]"
assert_type 'x = { a: 1, b: 2 }', 'x', 'Hash[Symbol, Integer]'
end

def test_hash_string_string
assert_type 'x = { "k" => "v" }', "x", "Hash[String, String]"
assert_type 'x = { "k" => "v" }', 'x', 'Hash[String, String]'
end

def test_hash_mixed_values
types = infer('x = { a: 1, b: "x" }')
assert_includes(
["Hash[Symbol, Integer | String]", "Hash[Symbol, String | Integer]"],
types["x"]
['Hash[Symbol, Integer | String]', 'Hash[Symbol, String | Integer]'],
types['x']
)
end

def test_hash_empty
assert_type "x = {}", "x", "Hash"
assert_type 'x = {}', 'x', 'Hash'
end

def test_hash_nested
assert_type "x = { a: [1] }", "x", "Hash[Symbol, Array[Integer]]"
assert_type 'x = { a: [1] }', 'x', 'Hash[Symbol, Array[Integer]]'
end

# ============================================
Expand Down
2 changes: 1 addition & 1 deletion test/integer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class IntegerTest < Minitest::Test
# ============================================

def test_integer_literal
assert_type "x = 42", "x", "Integer"
assert_type 'x = 42', 'x', 'Integer'
end

# ============================================
Expand Down
Loading