ruby-lsp 0.23.14 → 0.23.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/exe/ruby-lsp-launcher +9 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +2 -2
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +6 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +4 -2
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +60 -30
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +5 -4
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +5 -1
- data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
- data/lib/ruby_indexer/test/configuration_test.rb +6 -4
- data/lib/ruby_indexer/test/constant_test.rb +34 -34
- data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +139 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +118 -118
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +64 -70
- data/lib/ruby_indexer/test/test_case.rb +2 -2
- data/lib/ruby_lsp/document.rb +6 -1
- data/lib/ruby_lsp/erb_document.rb +12 -4
- data/lib/ruby_lsp/global_state.rb +1 -1
- data/lib/ruby_lsp/listeners/code_lens.rb +3 -3
- data/lib/ruby_lsp/listeners/completion.rb +24 -11
- data/lib/ruby_lsp/listeners/definition.rb +1 -1
- data/lib/ruby_lsp/listeners/document_link.rb +3 -1
- data/lib/ruby_lsp/listeners/document_symbol.rb +3 -3
- data/lib/ruby_lsp/listeners/folding_ranges.rb +8 -4
- data/lib/ruby_lsp/listeners/hover.rb +2 -2
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +12 -5
- data/lib/ruby_lsp/listeners/signature_help.rb +5 -1
- data/lib/ruby_lsp/listeners/spec_style.rb +1 -1
- data/lib/ruby_lsp/listeners/test_style.rb +8 -8
- data/lib/ruby_lsp/requests/code_action_resolve.rb +14 -15
- data/lib/ruby_lsp/requests/completion_resolve.rb +1 -1
- data/lib/ruby_lsp/requests/hover.rb +2 -2
- data/lib/ruby_lsp/requests/on_type_formatting.rb +4 -2
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +1 -2
- data/lib/ruby_lsp/requests/references.rb +2 -1
- data/lib/ruby_lsp/requests/rename.rb +8 -5
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +4 -4
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
- data/lib/ruby_lsp/requests/support/common.rb +3 -1
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/source_uri.rb +5 -3
- data/lib/ruby_lsp/response_builders/document_symbol.rb +3 -2
- data/lib/ruby_lsp/response_builders/hover.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/ruby_document.rb +2 -2
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +14 -5
- data/lib/ruby_lsp/setup_bundler.rb +7 -3
- data/lib/ruby_lsp/static_docs.rb +8 -1
- data/lib/ruby_lsp/store.rb +3 -2
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +164 -0
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
- data/lib/ruby_lsp/type_inferrer.rb +4 -1
- data/lib/ruby_lsp/utils.rb +12 -2
- metadata +6 -6
- data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +0 -109
- data/lib/ruby_lsp/test_reporter.rb +0 -207
- data/lib/ruby_lsp/test_unit_test_runner.rb +0 -98
| @@ -1,207 +0,0 @@ | |
| 1 | 
            -
            # typed: strict
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            require "json"
         | 
| 5 | 
            -
            require "delegate"
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            $stdout.binmode
         | 
| 8 | 
            -
            $stdout.sync = true
         | 
| 9 | 
            -
            $stderr.binmode
         | 
| 10 | 
            -
            $stderr.sync = true
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            module RubyLsp
         | 
| 13 | 
            -
              module TestReporter
         | 
| 14 | 
            -
                class << self
         | 
| 15 | 
            -
                  #: (id: String, uri: URI::Generic) -> void
         | 
| 16 | 
            -
                  def start_test(id:, uri:)
         | 
| 17 | 
            -
                    params = {
         | 
| 18 | 
            -
                      id: id,
         | 
| 19 | 
            -
                      uri: uri.to_s,
         | 
| 20 | 
            -
                    }
         | 
| 21 | 
            -
                    send_message("start", params)
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  #: (id: String, uri: URI::Generic) -> void
         | 
| 25 | 
            -
                  def record_pass(id:, uri:)
         | 
| 26 | 
            -
                    params = {
         | 
| 27 | 
            -
                      id: id,
         | 
| 28 | 
            -
                      uri: uri.to_s,
         | 
| 29 | 
            -
                    }
         | 
| 30 | 
            -
                    send_message("pass", params)
         | 
| 31 | 
            -
                  end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  #: (id: String, message: String, uri: URI::Generic) -> void
         | 
| 34 | 
            -
                  def record_fail(id:, message:, uri:)
         | 
| 35 | 
            -
                    params = {
         | 
| 36 | 
            -
                      id: id,
         | 
| 37 | 
            -
                      message: message,
         | 
| 38 | 
            -
                      uri: uri.to_s,
         | 
| 39 | 
            -
                    }
         | 
| 40 | 
            -
                    send_message("fail", params)
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  #: (id: String, uri: URI::Generic) -> void
         | 
| 44 | 
            -
                  def record_skip(id:, uri:)
         | 
| 45 | 
            -
                    params = {
         | 
| 46 | 
            -
                      id: id,
         | 
| 47 | 
            -
                      uri: uri.to_s,
         | 
| 48 | 
            -
                    }
         | 
| 49 | 
            -
                    send_message("skip", params)
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  #: (id: String, message: String?, uri: URI::Generic) -> void
         | 
| 53 | 
            -
                  def record_error(id:, message:, uri:)
         | 
| 54 | 
            -
                    params = {
         | 
| 55 | 
            -
                      id: id,
         | 
| 56 | 
            -
                      message: message,
         | 
| 57 | 
            -
                      uri: uri.to_s,
         | 
| 58 | 
            -
                    }
         | 
| 59 | 
            -
                    send_message("error", params)
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  #: (message: String) -> void
         | 
| 63 | 
            -
                  def append_output(message:)
         | 
| 64 | 
            -
                    params = {
         | 
| 65 | 
            -
                      message: message,
         | 
| 66 | 
            -
                    }
         | 
| 67 | 
            -
                    send_message("append_output", params)
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  # Gather the results returned by Coverage.result and format like the VS Code test explorer expects
         | 
| 71 | 
            -
                  #
         | 
| 72 | 
            -
                  # Coverage result format:
         | 
| 73 | 
            -
                  #
         | 
| 74 | 
            -
                  # Lines are reported in order as an array where each number is the number of times it was executed. For example,
         | 
| 75 | 
            -
                  # the following says that line 0 was executed 1 time and line 1 executed 3 times: [1, 3].
         | 
| 76 | 
            -
                  # Nil values represent lines for which coverage is not available, like empty lines, comments or keywords like
         | 
| 77 | 
            -
                  # `else`
         | 
| 78 | 
            -
                  #
         | 
| 79 | 
            -
                  # Branches are a hash containing the name of the branch and the location where it is found in tuples with the
         | 
| 80 | 
            -
                  # following elements: [NAME, ID, START_LINE, START_COLUMN, END_LINE, END_COLUMN] as the keys and the value is the
         | 
| 81 | 
            -
                  # number of times it was executed
         | 
| 82 | 
            -
                  #
         | 
| 83 | 
            -
                  # Methods are a similar hash [ClassName, :method_name, START_LINE, START_COLUMN, END_LINE, END_COLUMN] => NUMBER
         | 
| 84 | 
            -
                  # OF EXECUTIONS
         | 
| 85 | 
            -
                  #
         | 
| 86 | 
            -
                  # Example:
         | 
| 87 | 
            -
                  # {
         | 
| 88 | 
            -
                  #   "file_path" => {
         | 
| 89 | 
            -
                  #     "lines" => [1, 2, 3, nil],
         | 
| 90 | 
            -
                  #     "branches" => {
         | 
| 91 | 
            -
                  #       ["&.", 0, 6, 21, 6, 65] => { [:then, 1, 6, 21, 6, 65] => 0, [:else, 5, 7, 0, 7, 87] => 1 }
         | 
| 92 | 
            -
                  #     },
         | 
| 93 | 
            -
                  #     "methods" => {
         | 
| 94 | 
            -
                  #       ["Foo", :bar, 6, 21, 6, 65] => 0
         | 
| 95 | 
            -
                  #     }
         | 
| 96 | 
            -
                  # }
         | 
| 97 | 
            -
                  #: () -> Hash[String, StatementCoverage]
         | 
| 98 | 
            -
                  def gather_coverage_results
         | 
| 99 | 
            -
                    # Ignore coverage results inside dependencies
         | 
| 100 | 
            -
                    bundle_path = Bundler.bundle_path.to_s
         | 
| 101 | 
            -
                    default_gems_path = File.dirname(RbConfig::CONFIG["rubylibdir"])
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                    result = Coverage.result.reject do |file_path, _coverage_info|
         | 
| 104 | 
            -
                      file_path.start_with?(bundle_path) ||
         | 
| 105 | 
            -
                        file_path.start_with?(default_gems_path) ||
         | 
| 106 | 
            -
                        file_path.start_with?("eval")
         | 
| 107 | 
            -
                    end
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                    result.to_h do |file_path, coverage_info|
         | 
| 110 | 
            -
                      # Format the branch coverage information as VS Code expects it and then group it based on the start line of
         | 
| 111 | 
            -
                      # the conditional that causes the branching. We need to match each line coverage data with the branches that
         | 
| 112 | 
            -
                      # spawn from that line
         | 
| 113 | 
            -
                      branch_by_line = coverage_info[:branches]
         | 
| 114 | 
            -
                        .flat_map do |branch, data|
         | 
| 115 | 
            -
                          branch_name, _branch_id, branch_start_line, _branch_start_col, _branch_end_line, _branch_end_col = branch
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                          data.map do |then_or_else, execution_count|
         | 
| 118 | 
            -
                            name, _id, start_line, start_column, end_line, end_column = then_or_else
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                            {
         | 
| 121 | 
            -
                              groupingLine: branch_start_line,
         | 
| 122 | 
            -
                              executed: execution_count,
         | 
| 123 | 
            -
                              location: {
         | 
| 124 | 
            -
                                start: { line: start_line, character: start_column },
         | 
| 125 | 
            -
                                end: { line: end_line, character: end_column },
         | 
| 126 | 
            -
                              },
         | 
| 127 | 
            -
                              label: "#{branch_name} #{name}",
         | 
| 128 | 
            -
                            }
         | 
| 129 | 
            -
                          end
         | 
| 130 | 
            -
                        end
         | 
| 131 | 
            -
                        .group_by { |branch| branch[:groupingLine] }
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                      # Format the line coverage information, gathering any branch coverage data associated with that line
         | 
| 134 | 
            -
                      data = coverage_info[:lines].filter_map.with_index do |execution_count, line_index|
         | 
| 135 | 
            -
                        next if execution_count.nil?
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                        {
         | 
| 138 | 
            -
                          executed: execution_count,
         | 
| 139 | 
            -
                          location: { line: line_index, character: 0 },
         | 
| 140 | 
            -
                          branches: branch_by_line[line_index] || [],
         | 
| 141 | 
            -
                        }
         | 
| 142 | 
            -
                      end
         | 
| 143 | 
            -
             | 
| 144 | 
            -
                      # The expected format is URI => { executed: number_of_times_executed, location: { ... }, branches: [ ... ] }
         | 
| 145 | 
            -
                      [URI::Generic.from_path(path: File.expand_path(file_path)).to_s, data]
         | 
| 146 | 
            -
                    end
         | 
| 147 | 
            -
                  end
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                  private
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                  #: (method_name: String?, params: Hash[String, untyped]) -> void
         | 
| 152 | 
            -
                  def send_message(method_name, params)
         | 
| 153 | 
            -
                    json_message = { method: method_name, params: params }.to_json
         | 
| 154 | 
            -
                    ORIGINAL_STDOUT.write("Content-Length: #{json_message.bytesize}\r\n\r\n#{json_message}")
         | 
| 155 | 
            -
                  end
         | 
| 156 | 
            -
                end
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                ORIGINAL_STDOUT = $stdout #: IO
         | 
| 159 | 
            -
             | 
| 160 | 
            -
                class IOWrapper < SimpleDelegator
         | 
| 161 | 
            -
                  #: (Object) -> void
         | 
| 162 | 
            -
                  def puts(*args)
         | 
| 163 | 
            -
                    args.each { |arg| log(convert_line_breaks(arg) + "\r\n") }
         | 
| 164 | 
            -
                  end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                  #: (Object) -> void
         | 
| 167 | 
            -
                  def print(*args)
         | 
| 168 | 
            -
                    args.each { |arg| log(convert_line_breaks(arg)) }
         | 
| 169 | 
            -
                  end
         | 
| 170 | 
            -
             | 
| 171 | 
            -
                  #: (Object) -> void
         | 
| 172 | 
            -
                  def write(*args)
         | 
| 173 | 
            -
                    args.each { |arg| log(convert_line_breaks(arg)) }
         | 
| 174 | 
            -
                  end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                  private
         | 
| 177 | 
            -
             | 
| 178 | 
            -
                  #: (Object) -> String
         | 
| 179 | 
            -
                  def convert_line_breaks(message)
         | 
| 180 | 
            -
                    message.to_s.gsub("\n", "\r\n")
         | 
| 181 | 
            -
                  end
         | 
| 182 | 
            -
             | 
| 183 | 
            -
                  #: (String) -> void
         | 
| 184 | 
            -
                  def log(message)
         | 
| 185 | 
            -
                    TestReporter.append_output(message: message)
         | 
| 186 | 
            -
                  end
         | 
| 187 | 
            -
                end
         | 
| 188 | 
            -
              end
         | 
| 189 | 
            -
            end
         | 
| 190 | 
            -
             | 
| 191 | 
            -
            if ENV["RUBY_LSP_TEST_RUNNER"]
         | 
| 192 | 
            -
              # We wrap the default output stream so that we can capture anything written to stdout and emit it as part of the JSON
         | 
| 193 | 
            -
              # event stream.
         | 
| 194 | 
            -
              $> = RubyLsp::TestReporter::IOWrapper.new($stdout)
         | 
| 195 | 
            -
             | 
| 196 | 
            -
              if ENV["RUBY_LSP_TEST_RUNNER"] == "coverage"
         | 
| 197 | 
            -
                # Auto start coverage when running tests under that profile. This avoids the user from having to configure coverage
         | 
| 198 | 
            -
                # manually for their project or adding extra dependencies
         | 
| 199 | 
            -
                require "coverage"
         | 
| 200 | 
            -
                Coverage.start(:all)
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                at_exit do
         | 
| 203 | 
            -
                  coverage_results = RubyLsp::TestReporter.gather_coverage_results
         | 
| 204 | 
            -
                  File.write(File.join(".ruby-lsp", "coverage_result.json"), coverage_results.to_json)
         | 
| 205 | 
            -
                end
         | 
| 206 | 
            -
              end
         | 
| 207 | 
            -
            end
         | 
| @@ -1,98 +0,0 @@ | |
| 1 | 
            -
            # typed: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            begin
         | 
| 5 | 
            -
              require "test/unit"
         | 
| 6 | 
            -
              require "test/unit/ui/testrunner"
         | 
| 7 | 
            -
            rescue LoadError
         | 
| 8 | 
            -
              return
         | 
| 9 | 
            -
            end
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            require_relative "test_reporter"
         | 
| 12 | 
            -
            require "ruby_indexer/lib/ruby_indexer/uri"
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            module RubyLsp
         | 
| 15 | 
            -
              class TestRunner < ::Test::Unit::UI::TestRunner
         | 
| 16 | 
            -
                private
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                #: (::Test::Unit::TestCase test) -> void
         | 
| 19 | 
            -
                def test_started(test)
         | 
| 20 | 
            -
                  current_test = test
         | 
| 21 | 
            -
                  @current_uri = uri_for_test(current_test)
         | 
| 22 | 
            -
                  return unless @current_uri
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  @current_test_id = "#{current_test.class.name}##{current_test.method_name}"
         | 
| 25 | 
            -
                  TestReporter.start_test(
         | 
| 26 | 
            -
                    id: @current_test_id,
         | 
| 27 | 
            -
                    uri: @current_uri,
         | 
| 28 | 
            -
                  )
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                #: (::Test::Unit::TestCase test) -> void
         | 
| 32 | 
            -
                def test_finished(test)
         | 
| 33 | 
            -
                  if test.passed?
         | 
| 34 | 
            -
                    TestReporter.record_pass(
         | 
| 35 | 
            -
                      id: @current_test_id,
         | 
| 36 | 
            -
                      uri: @current_uri,
         | 
| 37 | 
            -
                    )
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                #: (::Test::Unit::Failure | ::Test::Unit::Error | ::Test::Unit::Pending result) -> void
         | 
| 42 | 
            -
                def result_fault(result)
         | 
| 43 | 
            -
                  case result
         | 
| 44 | 
            -
                  when ::Test::Unit::Failure
         | 
| 45 | 
            -
                    record_failure(result)
         | 
| 46 | 
            -
                  when ::Test::Unit::Error
         | 
| 47 | 
            -
                    record_error(result)
         | 
| 48 | 
            -
                  when ::Test::Unit::Pending
         | 
| 49 | 
            -
                    record_skip(result)
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                #: (::Test::Unit::Failure failure) -> void
         | 
| 54 | 
            -
                def record_failure(failure)
         | 
| 55 | 
            -
                  TestReporter.record_fail(
         | 
| 56 | 
            -
                    id: @current_test_id,
         | 
| 57 | 
            -
                    message: failure.message,
         | 
| 58 | 
            -
                    uri: @current_uri,
         | 
| 59 | 
            -
                  )
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                #: (::Test::Unit::Error error) -> void
         | 
| 63 | 
            -
                def record_error(error)
         | 
| 64 | 
            -
                  TestReporter.record_error(
         | 
| 65 | 
            -
                    id: @current_test_id,
         | 
| 66 | 
            -
                    message: error.message,
         | 
| 67 | 
            -
                    uri: @current_uri,
         | 
| 68 | 
            -
                  )
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                #: (::Test::Unit::Pending pending) -> void
         | 
| 72 | 
            -
                def record_skip(pending)
         | 
| 73 | 
            -
                  TestReporter.record_skip(id: @current_test_id, uri: @current_uri)
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                #: (::Test::Unit::TestCase test) -> URI::Generic?
         | 
| 77 | 
            -
                def uri_for_test(test)
         | 
| 78 | 
            -
                  location = test.method(test.method_name).source_location
         | 
| 79 | 
            -
                  return unless location # TODO: when might this be nil?
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  file, _line = location
         | 
| 82 | 
            -
                  return if file.start_with?("(eval at ") # test is dynamically defined (TODO: better way to check?)
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                  absolute_path = File.expand_path(file, Dir.pwd)
         | 
| 85 | 
            -
                  URI::Generic.from_path(path: absolute_path)
         | 
| 86 | 
            -
                end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                #: -> void
         | 
| 89 | 
            -
                def attach_to_mediator
         | 
| 90 | 
            -
                  @mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:result_fault))
         | 
| 91 | 
            -
                  @mediator.add_listener(Test::Unit::TestCase::STARTED_OBJECT, &method(:test_started))
         | 
| 92 | 
            -
                  @mediator.add_listener(Test::Unit::TestCase::FINISHED_OBJECT, &method(:test_finished))
         | 
| 93 | 
            -
                end
         | 
| 94 | 
            -
              end
         | 
| 95 | 
            -
            end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
            Test::Unit::AutoRunner.register_runner(:ruby_lsp) { |_auto_runner| RubyLsp::TestRunner }
         | 
| 98 | 
            -
            Test::Unit::AutoRunner.default_runner = :ruby_lsp
         |