Skip to content

Commit f96f643

Browse files
committed
Iron out creases in completion
1 parent 53e49ab commit f96f643

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

lib/ruby_lsp/rails/factory_bot/completion.rb

+48-9
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,50 @@ def process_arguments_pattern(node, arguments) # rubocop:disable Metrics/MethodL
3838
handle_factory(factory_name_node, node_string_value(factory_name_node))
3939

4040
in [Prism::SymbolNode => factory_name_node, *, Prism::SymbolNode => trait_node]
41-
handle_trait(node_string_value(factory_name_node), node, node_string_value(trait_node))
41+
already_used_traits = gather_already_used_traits(arguments)
42+
handle_trait(
43+
node_string_value(factory_name_node), node, already_used_traits, node_string_value(trait_node),
44+
)
4245

4346
in [Prism::SymbolNode => _factory_name_node, *, Prism::KeywordHashNode => _kw_node] |
4447
[Prism::SymbolNode => _factory_name_node, *, Prism::HashNode => _kw_node] |
4548
[Prism::SymbolNode => _factory_name_node, *, Prism::CallNode => _call_node]
4649

47-
attr_name = _call_node ? _call_node.message : _kw_node.elements.last.key.name&.to_s
48-
handle_attribute(node_string_value(_factory_name_node), node, attr_name)
50+
attr_name = node_string_value(_call_node || _kw_node.elements.last.key)
51+
already_used_attrs = gather_already_used_attrs(_kw_node)
52+
handle_attribute(node_string_value(_factory_name_node), node, already_used_attrs, attr_name)
4953
else
5054
nil
5155
end
5256
end
5357

5458
def node_string_value(node)
55-
node.value.to_s
59+
case node
60+
when Prism::CallNode
61+
node.name.to_s
62+
when Prism::SymbolNode
63+
node.value.to_s
64+
when nil
65+
""
66+
end
67+
end
68+
69+
def gather_already_used_attrs(kw_node)
70+
attrs = Set.new
71+
return attrs unless kw_node
72+
73+
kw_node.elements.each do |e|
74+
attrs.add(node_string_value(e.key))
75+
end
76+
77+
attrs
5678
end
5779

58-
def handle_attribute(factory_name, node, value = "")
80+
def handle_attribute(factory_name, node, already_used_attrs, value = "")
5981
range = range_from_node(node)
6082
make_request(:attributes, factory_name: factory_name, name: value)&.each do |attr|
83+
next if already_used_attrs.member?(attr[:name].to_s)
84+
6185
label_details = Interface::CompletionItemLabelDetails.new(description: attr[:type])
6286

6387
@response_builder << serialise_attribute(attr[:name], label_details, attr[:owner], range)
@@ -75,24 +99,39 @@ def serialise_attribute(name, label_details, owner, range)
7599
)
76100
end
77101

78-
def handle_trait(factory_name, node, value = "")
102+
def gather_already_used_traits(arguments)
103+
trait_names = Set.new
104+
# skip the first one because it's factory name
105+
1.upto(arguments.length - 1) do |i|
106+
arg = arguments[i]
107+
next if arg.is_a?(Prism::IntegerNode)
108+
break unless arg.is_a?(Prism::SymbolNode)
109+
110+
trait_names.add(arg.value.to_s)
111+
end
112+
trait_names
113+
end
114+
115+
def handle_trait(factory_name, node, already_used_traits, value = "")
79116
make_request(:traits, factory_name: factory_name, name: value)&.each do |tr|
117+
next if already_used_traits.member?(tr[:name].to_s)
118+
80119
label_details = Interface::CompletionItemLabelDetails.new(description: tr[:owner])
81120
range = range_from_node(node)
82121
name = tr[:name]
83122

84-
@response_builder << serialise_trait(name, range, label_details)
123+
@response_builder << serialise_trait(name, range, label_details, tr[:owner])
85124
end
86125
end
87126

88-
def serialise_trait(name, range, label_details)
127+
def serialise_trait(name, range, label_details, owner)
89128
Interface::CompletionItem.new(
90129
label: name,
91130
filter_text: name,
92131
label_details: label_details,
93132
text_edit: Interface::TextEdit.new(range: range, new_text: name),
94133
kind: Constant::CompletionItemKind::PROPERTY,
95-
data: { owner_name: nil, guessed_type: tr[:owner] },
134+
data: { owner_name: nil, guessed_type: owner },
96135
)
97136
end
98137

0 commit comments

Comments
 (0)