diff --git a/lib/steep/diagnostic/lsp_formatter.rb b/lib/steep/diagnostic/lsp_formatter.rb index 0adf1a5c0..654c303a0 100644 --- a/lib/steep/diagnostic/lsp_formatter.rb +++ b/lib/steep/diagnostic/lsp_formatter.rb @@ -41,7 +41,7 @@ def format(diagnostic) severity = severity_for(diagnostic) if severity - range = diagnostic.location&.as_lsp_range or raise + range = diagnostic.location&.as_lsp_range or raise "#{diagnostic.class} object (#{diagnostic.full_message}) instance must have `#location`" LSP::Interface::Diagnostic.new( message: diagnostic.full_message, diff --git a/lib/steep/diagnostic/ruby.rb b/lib/steep/diagnostic/ruby.rb index 04a332686..bfa2896e5 100644 --- a/lib/steep/diagnostic/ruby.rb +++ b/lib/steep/diagnostic/ruby.rb @@ -286,13 +286,14 @@ class NoMethod < Base def initialize(node:, type:, method:) loc = case node.type when :send - node.loc.selector + loc = _ = nil + loc ||= node.loc.operator if node.loc.respond_to?(:operator) + loc ||= node.loc.selector if node.loc.respond_to?(:selector) + loc when :block node.children[0].loc.selector - else - node.loc.expression end - super(node: node, location: loc) + super(node: node, location: loc || node.loc.expression) @type = type @method = method end diff --git a/test/type_construction_test.rb b/test/type_construction_test.rb index bd7ffffaf..f63b36c13 100644 --- a/test/type_construction_test.rb +++ b/test/type_construction_test.rb @@ -10449,4 +10449,24 @@ def test_orasgn_andasgn__global end end end + + def test_opasgn_error_report + with_checker(<<~RBS) do |checker| + RBS + source = parse_ruby(<<~RUBY) + x = [1].first + + x += 1 + RUBY + + with_standard_construction(checker, source) do |construction, typing| + type, _, context = construction.synthesize(source.node) + + assert_all!(typing.errors) do |error| + assert_operator error, :is_a?, Diagnostic::Ruby::NoMethod + assert_instance_of Parser::Source::Range, error.location + end + end + end + end end