diff --git a/lib/ruby_lsp/ruby_lsp_rails/completion.rb b/lib/ruby_lsp/ruby_lsp_rails/completion.rb index eb4f52e9..d2ead08e 100644 --- a/lib/ruby_lsp/ruby_lsp_rails/completion.rb +++ b/lib/ruby_lsp/ruby_lsp_rails/completion.rb @@ -38,19 +38,16 @@ def on_call_node_enter(node) sig { params(node: Prism::CallNode).void } def handle_active_record_where_completions(node) receiver = node.receiver + return if receiver && !receiver.is_a?(Prism::ConstantReadNode) return unless receiver resolved_class = @client.model(receiver.name.to_s) return if resolved_class.nil? - arguments_node = node.arguments - existing_args = {} - if arguments_node - arguments_node.arguments.each do |arg| - arg.elements.each do |a| - existing_args[a.key.unescaped] = true - end - end + arguments = node.arguments&.arguments + existing_args = T.let({},T::Hash[String, T::Boolean]) + if arguments.present? + existing_args = get_call_node_arguments(arguments: arguments) end resolved_class[:columns].each do |column| @@ -60,13 +57,32 @@ def handle_active_record_where_completions(node) label: column[0], filter_text: column[0], label_details: Interface::CompletionItemLabelDetails.new( - description: "Filter #{node.receiver.name} records by #{column[0]}", + description: "Filter #{receiver.name} records by #{column[0]}", ), text_edit: Interface::TextEdit.new(range: 0, new_text: "#{column[0]}: "), kind: Constant::CompletionItemKind::FIELD, ) end end + + sig { params(arguments: T::Array[Prism::Node]).returns(T::Hash[String, T::Boolean]) } + def get_call_node_arguments(arguments:) + existing_args = {} + arguments.each do |argument| + if argument.is_a?(Prism::KeywordHashNode) + argument.elements.each do |e| + if e.is_a?(Prism::AssocNode) + key = e.key + if key.is_a?(Prism::SymbolNode) + id = key.value + existing_args[id] = true + end + end + end + end + end + existing_args + end end end end diff --git a/test/ruby_lsp_rails/completion_test.rb b/test/ruby_lsp_rails/completion_test.rb index 0efdcbf3..bdc7636d 100644 --- a/test/ruby_lsp_rails/completion_test.rb +++ b/test/ruby_lsp_rails/completion_test.rb @@ -7,7 +7,7 @@ module RubyLsp module Rails class CompletionTest < ActiveSupport::TestCase test "recognizes Active Record .where call on an Active Record model when cursor is on (" do - response = generate_completions_for_source(<<~RUBY, { line: 2, character: 10 }) + response = generate_completions_for_source(<<~RUBY, { line: 1, character: 10 }) # typed: false User.where( RUBY @@ -31,7 +31,7 @@ class CompletionTest < ActiveSupport::TestCase end test "Does not suggest column if it already exists within .where as an arg and parantheses are not closed" do - response = generate_completions_for_source(<<~RUBY, { line: 2, character: 28 }) + response = generate_completions_for_source(<<~RUBY, { line: 1, character: 28 }) # typed: false User.where(id:, first_name:, RUBY @@ -46,7 +46,7 @@ class CompletionTest < ActiveSupport::TestCase end test "Does not suggest column if it already exists within .where as an arg and parantheses are closed" do - response = generate_completions_for_source(<<~RUBY, { line: 2, character: 28 }) + response = generate_completions_for_source(<<~RUBY, { line: 1, character: 28 }) # typed: false User.where(id:, first_name:, ) RUBY