Skip to content

Commit bfa3614

Browse files
authored
Add association augmentations (#423)
Add associations enhancement
1 parent 00b6b4c commit bfa3614

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

lib/ruby_lsp/ruby_lsp_rails/indexing_enhancement.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,61 @@ def on_call_node(index, owner, node, file_path)
2323
case name
2424
when :extend
2525
handle_concern_extend(index, owner, node)
26+
when :has_one, :has_many, :belongs_to, :has_and_belongs_to_many
27+
handle_association(index, owner, node, file_path)
2628
end
2729
end
2830

2931
private
3032

33+
sig do
34+
params(
35+
index: RubyIndexer::Index,
36+
owner: RubyIndexer::Entry::Namespace,
37+
node: Prism::CallNode,
38+
file_path: String,
39+
).void
40+
end
41+
def handle_association(index, owner, node, file_path)
42+
arguments = node.arguments&.arguments
43+
return unless arguments
44+
45+
name_arg = arguments.first
46+
47+
name = case name_arg
48+
when Prism::StringNode
49+
name_arg.content
50+
when Prism::SymbolNode
51+
name_arg.value
52+
end
53+
54+
return unless name
55+
56+
# Reader
57+
index.add(RubyIndexer::Entry::Method.new(
58+
name,
59+
file_path,
60+
name_arg.location,
61+
name_arg.location,
62+
[],
63+
[RubyIndexer::Entry::Signature.new([])],
64+
RubyIndexer::Entry::Visibility::PUBLIC,
65+
owner,
66+
))
67+
68+
# Writer
69+
index.add(RubyIndexer::Entry::Method.new(
70+
"#{name}=",
71+
file_path,
72+
name_arg.location,
73+
name_arg.location,
74+
[],
75+
[RubyIndexer::Entry::Signature.new([RubyIndexer::Entry::RequiredParameter.new(name: name.to_sym)])],
76+
RubyIndexer::Entry::Visibility::PUBLIC,
77+
owner,
78+
))
79+
end
80+
3181
sig do
3282
params(
3383
index: RubyIndexer::Index,

test/ruby_lsp_rails/indexing_enhancement_test.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,39 @@ class Post < ActiveRecord::Base
3434
assert_includes(ancestors, "ActiveRecord::Store::ClassMethods")
3535
assert_includes(ancestors, "ActiveRecord::AttributeMethods::ClassMethods")
3636
end
37+
38+
test "associations" do
39+
@index.index_single(RubyIndexer::IndexablePath.new(nil, "/fake.rb"), <<~RUBY)
40+
class Post < ActiveRecord::Base
41+
has_one :content
42+
belongs_to :author
43+
has_many :comments
44+
has_and_belongs_to_many :tags
45+
end
46+
RUBY
47+
48+
assert_declaration_on_line("content", "Post", 2)
49+
assert_declaration_on_line("content=", "Post", 2)
50+
51+
assert_declaration_on_line("author", "Post", 3)
52+
assert_declaration_on_line("author=", "Post", 3)
53+
54+
assert_declaration_on_line("comments", "Post", 4)
55+
assert_declaration_on_line("comments=", "Post", 4)
56+
57+
assert_declaration_on_line("tags", "Post", 5)
58+
assert_declaration_on_line("tags=", "Post", 5)
59+
end
60+
61+
private
62+
63+
def assert_declaration_on_line(method_name, class_name, line)
64+
association_entries = @index.resolve_method(method_name, class_name)
65+
refute_nil(association_entries)
66+
67+
association = association_entries.first
68+
assert_equal(line, association.location.start_line)
69+
end
3770
end
3871
end
3972
end

0 commit comments

Comments
 (0)