solargraph 0.58.3 → 0.59.0

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.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +6 -5
  4. data/.github/workflows/plugins.yml +46 -34
  5. data/.github/workflows/rspec.yml +15 -28
  6. data/.github/workflows/typecheck.yml +3 -2
  7. data/.rubocop.yml +38 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +12 -0
  10. data/Gemfile +3 -1
  11. data/README.md +3 -3
  12. data/Rakefile +26 -23
  13. data/bin/solargraph +2 -1
  14. data/lib/solargraph/api_map/cache.rb +3 -3
  15. data/lib/solargraph/api_map/constants.rb +12 -3
  16. data/lib/solargraph/api_map/index.rb +29 -18
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +39 -28
  19. data/lib/solargraph/api_map.rb +156 -72
  20. data/lib/solargraph/bench.rb +2 -3
  21. data/lib/solargraph/complex_type/conformance.rb +176 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +30 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +216 -57
  24. data/lib/solargraph/complex_type.rb +171 -58
  25. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  26. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  27. data/lib/solargraph/convention/data_definition.rb +5 -2
  28. data/lib/solargraph/convention/gemfile.rb +1 -1
  29. data/lib/solargraph/convention/gemspec.rb +1 -1
  30. data/lib/solargraph/convention/rakefile.rb +1 -1
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  33. data/lib/solargraph/convention/struct_definition.rb +8 -4
  34. data/lib/solargraph/convention.rb +2 -2
  35. data/lib/solargraph/converters/dd.rb +2 -0
  36. data/lib/solargraph/converters/dl.rb +2 -0
  37. data/lib/solargraph/converters/dt.rb +2 -0
  38. data/lib/solargraph/converters/misc.rb +2 -0
  39. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  40. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  41. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  42. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  43. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  44. data/lib/solargraph/doc_map.rb +38 -39
  45. data/lib/solargraph/equality.rb +4 -4
  46. data/lib/solargraph/gem_pins.rb +6 -6
  47. data/lib/solargraph/language_server/error_codes.rb +10 -10
  48. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  49. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  50. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  51. data/lib/solargraph/language_server/host/sources.rb +2 -1
  52. data/lib/solargraph/language_server/host.rb +30 -22
  53. data/lib/solargraph/language_server/message/base.rb +1 -1
  54. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  55. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  56. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  57. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  58. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  59. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  60. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  61. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  62. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  63. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  64. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  65. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  66. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  67. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  68. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  69. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  70. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  71. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  72. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  73. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  74. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  75. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  76. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  77. data/lib/solargraph/language_server/message.rb +1 -1
  78. data/lib/solargraph/language_server/request.rb +4 -2
  79. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  80. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  81. data/lib/solargraph/library.rb +57 -38
  82. data/lib/solargraph/location.rb +17 -14
  83. data/lib/solargraph/logging.rb +22 -4
  84. data/lib/solargraph/page.rb +1 -1
  85. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  86. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  87. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  88. data/lib/solargraph/parser/node_processor.rb +8 -7
  89. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  90. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  91. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  92. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  93. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  94. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  95. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  96. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  97. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  98. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  99. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  100. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  101. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  102. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  103. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  104. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  105. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  107. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  108. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  109. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  110. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  111. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  112. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  113. data/lib/solargraph/parser/parser_gem.rb +2 -0
  114. data/lib/solargraph/parser/region.rb +9 -3
  115. data/lib/solargraph/parser/snippet.rb +3 -1
  116. data/lib/solargraph/parser.rb +2 -0
  117. data/lib/solargraph/pin/base.rb +124 -80
  118. data/lib/solargraph/pin/base_variable.rb +273 -24
  119. data/lib/solargraph/pin/block.rb +29 -6
  120. data/lib/solargraph/pin/breakable.rb +7 -1
  121. data/lib/solargraph/pin/callable.rb +65 -21
  122. data/lib/solargraph/pin/closure.rb +7 -10
  123. data/lib/solargraph/pin/common.rb +24 -6
  124. data/lib/solargraph/pin/compound_statement.rb +55 -0
  125. data/lib/solargraph/pin/constant.rb +3 -5
  126. data/lib/solargraph/pin/conversions.rb +10 -4
  127. data/lib/solargraph/pin/delegated_method.rb +19 -8
  128. data/lib/solargraph/pin/documenting.rb +4 -2
  129. data/lib/solargraph/pin/instance_variable.rb +5 -1
  130. data/lib/solargraph/pin/keyword.rb +0 -4
  131. data/lib/solargraph/pin/local_variable.rb +15 -59
  132. data/lib/solargraph/pin/method.rb +156 -104
  133. data/lib/solargraph/pin/method_alias.rb +8 -0
  134. data/lib/solargraph/pin/namespace.rb +19 -12
  135. data/lib/solargraph/pin/parameter.rb +100 -36
  136. data/lib/solargraph/pin/proxy_type.rb +4 -1
  137. data/lib/solargraph/pin/reference/override.rb +1 -1
  138. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  139. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  140. data/lib/solargraph/pin/reference.rb +20 -0
  141. data/lib/solargraph/pin/search.rb +3 -2
  142. data/lib/solargraph/pin/signature.rb +15 -12
  143. data/lib/solargraph/pin/symbol.rb +2 -1
  144. data/lib/solargraph/pin/until.rb +2 -4
  145. data/lib/solargraph/pin/while.rb +2 -4
  146. data/lib/solargraph/pin.rb +2 -0
  147. data/lib/solargraph/pin_cache.rb +22 -19
  148. data/lib/solargraph/position.rb +17 -10
  149. data/lib/solargraph/range.rb +16 -15
  150. data/lib/solargraph/rbs_map/conversions.rb +358 -229
  151. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  152. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  153. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  154. data/lib/solargraph/rbs_map.rb +76 -32
  155. data/lib/solargraph/server_methods.rb +1 -1
  156. data/lib/solargraph/shell.rb +258 -66
  157. data/lib/solargraph/source/chain/array.rb +4 -2
  158. data/lib/solargraph/source/chain/call.rb +96 -56
  159. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  160. data/lib/solargraph/source/chain/constant.rb +5 -1
  161. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  162. data/lib/solargraph/source/chain/hash.rb +8 -5
  163. data/lib/solargraph/source/chain/if.rb +12 -10
  164. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  165. data/lib/solargraph/source/chain/link.rb +12 -22
  166. data/lib/solargraph/source/chain/literal.rb +9 -6
  167. data/lib/solargraph/source/chain/or.rb +10 -4
  168. data/lib/solargraph/source/chain/q_call.rb +2 -0
  169. data/lib/solargraph/source/chain/variable.rb +3 -1
  170. data/lib/solargraph/source/chain/z_super.rb +1 -3
  171. data/lib/solargraph/source/chain.rb +51 -38
  172. data/lib/solargraph/source/change.rb +12 -5
  173. data/lib/solargraph/source/cursor.rb +23 -17
  174. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  175. data/lib/solargraph/source/source_chainer.rb +56 -32
  176. data/lib/solargraph/source/updater.rb +5 -1
  177. data/lib/solargraph/source.rb +59 -35
  178. data/lib/solargraph/source_map/clip.rb +48 -29
  179. data/lib/solargraph/source_map/data.rb +4 -1
  180. data/lib/solargraph/source_map/mapper.rb +69 -42
  181. data/lib/solargraph/source_map.rb +21 -9
  182. data/lib/solargraph/type_checker/problem.rb +3 -1
  183. data/lib/solargraph/type_checker/rules.rb +81 -8
  184. data/lib/solargraph/type_checker.rb +195 -121
  185. data/lib/solargraph/version.rb +1 -1
  186. data/lib/solargraph/workspace/config.rb +14 -11
  187. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  188. data/lib/solargraph/workspace/require_paths.rb +1 -0
  189. data/lib/solargraph/workspace.rb +50 -28
  190. data/lib/solargraph/yard_map/helpers.rb +8 -3
  191. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  192. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  193. data/lib/solargraph/yard_map/mapper.rb +13 -8
  194. data/lib/solargraph/yard_map.rb +17 -18
  195. data/lib/solargraph/yard_tags.rb +2 -2
  196. data/lib/solargraph/yardoc.rb +7 -4
  197. data/lib/solargraph.rb +31 -8
  198. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  199. data/rbs/fills/tuple/tuple.rbs +28 -0
  200. data/rbs/shims/ast/0/node.rbs +1 -1
  201. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  202. data/solargraph.gemspec +37 -35
  203. metadata +41 -41
  204. data/lib/solargraph/type_checker/checks.rb +0 -124
  205. data/lib/solargraph/type_checker/param_def.rb +0 -37
  206. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -17,6 +17,7 @@ module Solargraph
17
17
  type: :class,
18
18
  location: loc,
19
19
  closure: region.closure,
20
+ # @sg-ignore flow sensitive typing needs to handle attrs
20
21
  name: struct_definition_node.class_name,
21
22
  docstring: docstring,
22
23
  visibility: :public,
@@ -39,6 +40,7 @@ module Solargraph
39
40
 
40
41
  pins.push initialize_method_pin
41
42
 
43
+ # @sg-ignore flow sensitive typing needs to handle attrs
42
44
  struct_definition_node.attributes.map do |attribute_node, attribute_name|
43
45
  initialize_method_pin.parameters.push(
44
46
  Pin::Parameter.new(
@@ -52,6 +54,7 @@ module Solargraph
52
54
  end
53
55
 
54
56
  # define attribute accessors and instance variables
57
+ # @sg-ignore flow sensitive typing needs to handle attrs
55
58
  struct_definition_node.attributes.each do |attribute_node, attribute_name|
56
59
  [attribute_name, "#{attribute_name}="].each do |name|
57
60
  docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
@@ -102,7 +105,7 @@ module Solargraph
102
105
 
103
106
  private
104
107
 
105
- # @return [StructDefintionNode, StructAssignmentNode, nil]
108
+ # @return [StructDefinition::StructDefintionNode, StructDefinition::StructAssignmentNode, nil]
106
109
  def struct_definition_node
107
110
  @struct_definition_node ||= if StructDefintionNode.match?(node)
108
111
  StructDefintionNode.new(node)
@@ -121,6 +124,7 @@ module Solargraph
121
124
  # @return [YARD::Docstring]
122
125
  def parse_comments
123
126
  struct_comments = comments_for(node) || ''
127
+ # @sg-ignore Need to add nil check here
124
128
  struct_definition_node.attributes.each do |attr_node, attr_name|
125
129
  comment = comments_for(attr_node)
126
130
  next if comment.nil?
@@ -138,7 +142,7 @@ module Solargraph
138
142
  # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
139
143
  #
140
144
  # @return [String]
141
- def tag_string(tag)
145
+ def tag_string tag
142
146
  tag&.types&.join(',') || 'undefined'
143
147
  end
144
148
 
@@ -146,8 +150,8 @@ module Solargraph
146
150
  # @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
147
151
  #
148
152
  # @return [String] The formatted comment for the attribute
149
- def attribute_comment(tag, for_setter)
150
- return "" if tag.nil?
153
+ def attribute_comment tag, for_setter
154
+ return '' if tag.nil?
151
155
 
152
156
  suffix = "[#{tag_string(tag)}] #{tag.text}"
153
157
 
@@ -30,7 +30,7 @@ module Solargraph
30
30
 
31
31
  # @param source_map [SourceMap]
32
32
  # @return [Environ]
33
- def self.for_local(source_map)
33
+ def self.for_local source_map
34
34
  result = Environ.new
35
35
  @@conventions.each do |conv|
36
36
  result.merge conv.local(source_map)
@@ -40,7 +40,7 @@ module Solargraph
40
40
 
41
41
  # @param doc_map [DocMap]
42
42
  # @return [Environ]
43
- def self.for_global(doc_map)
43
+ def self.for_global doc_map
44
44
  result = Environ.new
45
45
  @@conventions.each do |conv|
46
46
  result.merge conv.global(doc_map)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
 
3
5
  module ReverseMarkdown
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ReverseMarkdown
2
4
  module Converters
3
5
  class Dl < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ReverseMarkdown
2
4
  module Converters
3
5
  class Dt < Base
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ReverseMarkdown::Converters.register :tt, ReverseMarkdown::Converters::Code.new
@@ -10,6 +10,7 @@ module Solargraph
10
10
  return [] unless source.parsed? && source.synchronized?
11
11
  result = []
12
12
  refs = {}
13
+ # @sg-ignore Need to add nil check here
13
14
  map = api_map.source_map(source.filename)
14
15
  map.requires.each { |ref| refs[ref.name] = ref }
15
16
  api_map.missing_docs.each do |r|
@@ -17,7 +17,7 @@ module Solargraph
17
17
  'warning' => Severities::WARNING,
18
18
  'error' => Severities::ERROR,
19
19
  'fatal' => Severities::ERROR
20
- }
20
+ }.freeze
21
21
 
22
22
  # @param source [Solargraph::Source]
23
23
  # @param _api_map [Solargraph::ApiMap]
@@ -25,6 +25,7 @@ module Solargraph
25
25
  def diagnose source, _api_map
26
26
  @source = source
27
27
  require_rubocop(rubocop_version)
28
+ # @sg-ignore Need to add nil check here
28
29
  options, paths = generate_options(source.filename, source.code)
29
30
  store = RuboCop::ConfigStore.new
30
31
  runner = RuboCop::Runner.new(options, store)
@@ -32,7 +33,7 @@ module Solargraph
32
33
  # a time - it uses 'chdir' to read config files with ERB,
33
34
  # which can conflict with other chdirs.
34
35
  result = Solargraph::CHDIR_MUTEX.synchronize do
35
- redirect_stdout{ runner.run(paths) }
36
+ redirect_stdout { runner.run(paths) }
36
37
  end
37
38
 
38
39
  return [] if result.empty?
@@ -76,7 +77,7 @@ module Solargraph
76
77
  severity: SEVERITIES[off['severity']],
77
78
  source: 'rubocop',
78
79
  code: off['cop_name'],
79
- message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
80
+ message: off['message'].gsub(/^#{off['cop_name']}:/, '')
80
81
  }
81
82
  end
82
83
 
@@ -95,22 +96,22 @@ module Solargraph
95
96
  # @param off [Hash{String => Hash{String => Integer}}]
96
97
  # @return [Position]
97
98
  def offense_ending_position off
98
- if off['location']['start_line'] != off['location']['last_line']
99
- Position.new(off['location']['start_line'], 0)
100
- else
99
+ if off['location']['start_line'] == off['location']['last_line']
101
100
  start_line = off['location']['start_line'] - 1
102
101
  # @type [Integer]
103
102
  last_column = off['location']['last_column']
104
103
  line = @source.code.lines[start_line]
105
104
  col_off = if line.nil? || line.empty?
106
- 1
107
- else
108
- 0
109
- end
105
+ 1
106
+ else
107
+ 0
108
+ end
110
109
 
111
110
  Position.new(
112
111
  start_line, last_column - col_off
113
112
  )
113
+ else
114
+ Position.new(off['location']['start_line'], 0)
114
115
  end
115
116
  end
116
117
  end
@@ -13,17 +13,18 @@ module Solargraph
13
13
  # @param version [String, nil]
14
14
  # @raise [InvalidRubocopVersionError] if _version_ is not installed
15
15
  # @return [void]
16
- def require_rubocop(version = nil)
16
+ def require_rubocop version = nil
17
17
  begin
18
18
  # @type [String]
19
19
  gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
20
20
  gem_lib_path = File.join(gem_path, 'lib')
21
+ # @sg-ignore Should better support meaning of '&' in RBS
21
22
  $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
22
23
  rescue Gem::MissingSpecVersionError => e
23
24
  # @type [Array<Gem::Specification>]
24
25
  specs = e.specs
25
26
  raise InvalidRubocopVersionError,
26
- "could not find '#{e.name}' (#{e.requirement}) - "\
27
+ "could not find '#{e.name}' (#{e.requirement}) - " \
27
28
  "did find: [#{specs.map { |s| s.version.version }.join(', ')}]"
28
29
  end
29
30
  require 'rubocop'
@@ -50,7 +51,8 @@ module Solargraph
50
51
  # @return [String]
51
52
  def fix_drive_letter path
52
53
  return path unless path.match(/^[a-z]:/)
53
- path[0].upcase + path[1..-1]
54
+ # @sg-ignore Need to add nil check here
55
+ path[0].upcase + path[1..]
54
56
  end
55
57
 
56
58
  # @todo This is a smelly way to redirect output, but the RuboCop specs do
@@ -10,18 +10,19 @@ module Solargraph
10
10
  def diagnose source, api_map
11
11
  # return [] unless args.include?('always') || api_map.workspaced?(source.filename)
12
12
  severity = Diagnostics::Severities::ERROR
13
- level = (args.reverse.find { |a| ['normal', 'typed', 'strict', 'strong'].include?(a) }) || :normal
13
+ level = args.reverse.find { |a| %w[normal typed strict strong].include?(a) } || :normal
14
+ # @sg-ignore sensitive typing needs to handle || on nil types
14
15
  checker = Solargraph::TypeChecker.new(source.filename, api_map: api_map, level: level.to_sym)
15
16
  checker.problems
16
- .sort { |a, b| a.location.range.start.line <=> b.location.range.start.line }
17
- .map do |problem|
18
- {
19
- range: extract_first_line(problem.location, source),
20
- severity: severity,
21
- source: 'Typecheck',
22
- message: problem.message
23
- }
24
- end
17
+ .sort { |a, b| a.location.range.start.line <=> b.location.range.start.line }
18
+ .map do |problem|
19
+ {
20
+ range: extract_first_line(problem.location, source),
21
+ severity: severity,
22
+ source: 'Typecheck',
23
+ message: problem.message
24
+ }
25
+ end
25
26
  end
26
27
 
27
28
  private
@@ -4,16 +4,12 @@ module Solargraph
4
4
  module Diagnostics
5
5
  class UpdateErrors < Base
6
6
  def diagnose source, api_map
7
- result = []
8
- combine_ranges(source.code, source.error_ranges).each do |range|
9
- result.push(
10
- range: range.to_hash,
7
+ combine_ranges(source.code, source.error_ranges).map do |range|
8
+ { range: range.to_hash,
11
9
  severity: Diagnostics::Severities::ERROR,
12
10
  source: 'Solargraph',
13
- message: 'Syntax error'
14
- )
11
+ message: 'Syntax error' }
15
12
  end
16
- result
17
13
  end
18
14
 
19
15
  private
@@ -26,7 +22,7 @@ module Solargraph
26
22
  def combine_ranges code, ranges
27
23
  result = []
28
24
  lines = []
29
- ranges.sort{|a, b| a.start.line <=> b.start.line}.each do |rng|
25
+ ranges.sort { |a, b| a.start.line <=> b.start.line }.each do |rng|
30
26
  next if rng.nil? || lines.include?(rng.start.line)
31
27
  lines.push rng.start.line
32
28
  next if rng.start.line >= code.lines.length
@@ -46,11 +46,10 @@ module Solargraph
46
46
  attr_reader :environ
47
47
 
48
48
  # @param requires [Array<String>]
49
- # @param preferences [Array<Gem::Specification>]
50
49
  # @param workspace [Workspace, nil]
51
- def initialize(requires, preferences, workspace = nil)
50
+ # @param [Object] out
51
+ def initialize requires, workspace, out: $stderr
52
52
  @requires = requires.compact
53
- @preferences = preferences.compact
54
53
  @workspace = workspace
55
54
  @rbs_collection_path = workspace&.rbs_collection_path
56
55
  @rbs_collection_config_path = workspace&.rbs_collection_config_path
@@ -58,11 +57,13 @@ module Solargraph
58
57
  @requires.concat @environ.requires if @environ
59
58
  load_serialized_gem_pins
60
59
  pins.concat @environ.pins
60
+ @out = out
61
61
  end
62
62
 
63
- # @param out [IO]
63
+ # @param out [IO, StringIO, nil]
64
64
  # @return [void]
65
- def cache_all!(out)
65
+ # @param [Boolean] rebuild
66
+ def cache_all! out, rebuild: false
66
67
  # if we log at debug level:
67
68
  if logger.info?
68
69
  gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ')
@@ -72,7 +73,7 @@ module Solargraph
72
73
  logger.debug { "Caching for RBS collection: #{uncached_rbs_collection_gemspecs.map(&:name)}" }
73
74
  load_serialized_gem_pins
74
75
  uncached_gemspecs.each do |gemspec|
75
- cache(gemspec, out: out)
76
+ cache(gemspec, rebuild: rebuild, out: out)
76
77
  end
77
78
  load_serialized_gem_pins
78
79
  @uncached_rbs_collection_gemspecs = []
@@ -80,18 +81,18 @@ module Solargraph
80
81
  end
81
82
 
82
83
  # @param gemspec [Gem::Specification]
83
- # @param out [IO]
84
+ # @param out [IO, StringIO, nil]
84
85
  # @return [void]
85
- def cache_yard_pins(gemspec, out)
86
+ def cache_yard_pins gemspec, out
86
87
  pins = GemPins.build_yard_pins(yard_plugins, gemspec)
87
88
  PinCache.serialize_yard_gem(gemspec, pins)
88
89
  logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
89
90
  end
90
91
 
91
92
  # @param gemspec [Gem::Specification]
92
- # @param out [IO]
93
+ # @param out [IO, StringIO, nil]
93
94
  # @return [void]
94
- def cache_rbs_collection_pins(gemspec, out)
95
+ def cache_rbs_collection_pins gemspec, out
95
96
  rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
96
97
  pins = rbs_map.pins
97
98
  rbs_version_cache_key = rbs_map.cache_key
@@ -103,16 +104,16 @@ module Solargraph
103
104
 
104
105
  # @param gemspec [Gem::Specification]
105
106
  # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
106
- # @param out [IO, nil] output stream for logging
107
+ # @param out [IO, StringIO, nil] output stream for logging
107
108
  # @return [void]
108
- def cache(gemspec, rebuild: false, out: nil)
109
+ def cache gemspec, rebuild: false, out: nil
109
110
  build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild
110
111
  build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
111
112
  if build_yard || build_rbs_collection
112
113
  type = []
113
114
  type << 'YARD' if build_yard
114
115
  type << 'RBS collection' if build_rbs_collection
115
- out.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}") if out
116
+ out&.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}")
116
117
  end
117
118
  cache_yard_pins(gemspec, out) if build_yard
118
119
  cache_rbs_collection_pins(gemspec, out) if build_rbs_collection
@@ -130,12 +131,12 @@ module Solargraph
130
131
 
131
132
  # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
132
133
  def self.all_yard_gems_in_memory
133
- @yard_gems_in_memory ||= {}
134
+ @all_yard_gems_in_memory ||= {}
134
135
  end
135
136
 
136
137
  # @return [Hash{String => Hash{Array(String, String) => Array<Pin::Base>}}] stored by RBS collection path
137
138
  def self.all_rbs_collection_gems_in_memory
138
- @rbs_collection_gems_in_memory ||= {}
139
+ @all_rbs_collection_gems_in_memory ||= {}
139
140
  end
140
141
 
141
142
  # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
@@ -145,12 +146,13 @@ module Solargraph
145
146
 
146
147
  # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
147
148
  def rbs_collection_pins_in_memory
149
+ # @sg-ignore rbs_collection_path is String | nil but used as hash key
148
150
  self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
149
151
  end
150
152
 
151
153
  # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
152
154
  def self.all_combined_pins_in_memory
153
- @combined_pins_in_memory ||= {}
155
+ @all_combined_pins_in_memory ||= {}
154
156
  end
155
157
 
156
158
  # @todo this should also include an index by the hash of the RBS collection
@@ -177,18 +179,16 @@ module Solargraph
177
179
  @uncached_yard_gemspecs = []
178
180
  @uncached_rbs_collection_gemspecs = []
179
181
  with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
180
- # @sg-ignore Need support for RBS duck interfaces like _ToHash
181
182
  # @type [Array<String>]
182
- paths = Hash[without_gemspecs].keys
183
- # @sg-ignore Need support for RBS duck interfaces like _ToHash
183
+ paths = without_gemspecs.to_h.keys
184
184
  # @type [Array<Gem::Specification>]
185
- gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a
185
+ gemspecs = with_gemspecs.to_h.values.flatten.compact + dependencies.to_a
186
186
 
187
187
  paths.each do |path|
188
- rbs_pins = deserialize_stdlib_rbs_map path
188
+ deserialize_stdlib_rbs_map path
189
189
  end
190
190
 
191
- logger.debug { "DocMap#load_serialized_gem_pins: Combining pins..." }
191
+ logger.debug { 'DocMap#load_serialized_gem_pins: Combining pins...' }
192
192
  time = Benchmark.measure do
193
193
  gemspecs.each do |gemspec|
194
194
  pins = deserialize_combined_pin_cache gemspec
@@ -232,7 +232,7 @@ module Solargraph
232
232
 
233
233
  # @param gemspec [Gem::Specification]
234
234
  # @return [void]
235
- def deserialize_combined_pin_cache(gemspec)
235
+ def deserialize_combined_pin_cache gemspec
236
236
  unless combined_pins_in_memory[[gemspec.name, gemspec.version]].nil?
237
237
  return combined_pins_in_memory[[gemspec.name, gemspec.version]]
238
238
  end
@@ -263,14 +263,14 @@ module Solargraph
263
263
  if !yard_pins.nil?
264
264
  logger.debug { "Using only YARD pins for #{gemspec.name}:#{gemspec.version}" }
265
265
  combined_pins_in_memory[[gemspec.name, gemspec.version]] = yard_pins
266
- return combined_pins_in_memory[[gemspec.name, gemspec.version]]
266
+ combined_pins_in_memory[[gemspec.name, gemspec.version]]
267
267
  elsif !rbs_collection_pins.nil?
268
268
  logger.debug { "Using only RBS collection pins for #{gemspec.name}:#{gemspec.version}" }
269
269
  combined_pins_in_memory[[gemspec.name, gemspec.version]] = rbs_collection_pins
270
- return combined_pins_in_memory[[gemspec.name, gemspec.version]]
270
+ combined_pins_in_memory[[gemspec.name, gemspec.version]]
271
271
  else
272
272
  logger.debug { "Pins not yet cached for #{gemspec.name}:#{gemspec.version}" }
273
- return nil
273
+ nil
274
274
  end
275
275
  end
276
276
 
@@ -322,9 +322,7 @@ module Solargraph
322
322
  # a Gemfile; Gem doesn't try to index the paths in that case.
323
323
  #
324
324
  # See if we can make a good guess:
325
- potential_gemspec = Gem::Specification.find_by_name(gem_name_guess)
326
- file = "lib/#{path}.rb"
327
- gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
325
+ gemspec = Gem::Specification.find_by_name(gem_name_guess)
328
326
  rescue Gem::MissingSpecError
329
327
  logger.debug { "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}" }
330
328
  []
@@ -346,7 +344,7 @@ module Solargraph
346
344
  end
347
345
 
348
346
  # @param gemspec [Gem::Specification]
349
- # @param version [Gem::Version]
347
+ # @param version [Gem::Version, String]
350
348
  # @return [Gem::Specification]
351
349
  def change_gemspec_version gemspec, version
352
350
  Gem::Specification.find_by_name(gemspec.name, "= #{version}")
@@ -364,12 +362,10 @@ module Solargraph
364
362
  Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
365
363
  dep = Gem.loaded_specs[spec.name]
366
364
  # @todo is next line necessary?
367
- # @sg-ignore Unresolved call to requirement on Gem::Dependency
368
365
  dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
369
366
  deps.merge fetch_dependencies(dep) if deps.add?(dep)
370
367
  rescue Gem::MissingSpecError
371
- # @sg-ignore Unresolved call to requirement on Gem::Dependency
372
- Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found in RubyGems."
368
+ Solargraph.logger.warn "Gem dependency #{spec.name} for #{gemspec.name} not found in RubyGems."
373
369
  end.to_a
374
370
  end
375
371
 
@@ -379,7 +375,6 @@ module Solargraph
379
375
  gemspec.dependencies - gemspec.development_dependencies
380
376
  end
381
377
 
382
-
383
378
  def inspect
384
379
  self.class.inspect
385
380
  end
@@ -387,9 +382,10 @@ module Solargraph
387
382
  # @return [Array<Gem::Specification>, nil]
388
383
  def gemspecs_required_from_bundler
389
384
  # @todo Handle projects with custom Bundler/Gemfile setups
390
- return unless workspace.gemfile?
385
+ return unless workspace&.gemfile?
391
386
 
392
- if workspace.gemfile? && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory)
387
+ # @sg-ignore workspace is checked for nil above
388
+ if workspace.gemfile? && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory) # rubocop:disable Style/SafeNavigationChainLength
393
389
  # Find only the gems bundler is now using
394
390
  Bundler.definition.locked_gems.specs.flat_map do |lazy_spec|
395
391
  logger.info "Handling #{lazy_spec.name}:#{lazy_spec.version}"
@@ -407,7 +403,7 @@ module Solargraph
407
403
  end
408
404
  end
409
405
 
410
- # @return [Array<Gem::Specification>, nil]
406
+ # @return [Array<Gem::Specification>]
411
407
  def gemspecs_required_from_external_bundle
412
408
  logger.info 'Fetching gemspecs required from external bundle'
413
409
  return [] unless workspace&.directory
@@ -415,7 +411,8 @@ module Solargraph
415
411
  Solargraph.with_clean_env do
416
412
  cmd = [
417
413
  'ruby', '-e',
418
- "require 'bundler'; require 'json'; Dir.chdir('#{workspace&.directory}') { puts Bundler.definition.locked_gems.specs.map { |spec| [spec.name, spec.version] }.to_h.to_json }"
414
+ # @sg-ignore return above ensures workspace.directory is not nil
415
+ "require 'bundler'; require 'json'; Dir.chdir('#{workspace.directory}') { puts Bundler.definition.locked_gems.specs.map { |spec| [spec.name, spec.version] }.to_h.to_json }"
419
416
  ]
420
417
  o, e, s = Open3.capture3(*cmd)
421
418
  if s.success?
@@ -431,7 +428,9 @@ module Solargraph
431
428
  next specs
432
429
  end.compact
433
430
  else
434
- Solargraph.logger.warn "Failed to load gems from bundle at #{workspace&.directory}: #{e}"
431
+ # @sg-ignore return above ensures workspace.directory is not nil
432
+ Solargraph.logger.warn "Failed to load gems from bundle at #{workspace.directory}: #{e}"
433
+ []
435
434
  end
436
435
  end
437
436
  end
@@ -10,16 +10,16 @@ module Solargraph
10
10
 
11
11
  # @param other [Object]
12
12
  # @return [Boolean]
13
- def eql?(other)
13
+ def eql? other
14
14
  self.class.eql?(other.class) &&
15
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
15
+ # @sg-ignore flow sensitive typing should support .class == .class
16
16
  equality_fields.eql?(other.equality_fields)
17
17
  end
18
18
 
19
19
  # @param other [Object]
20
20
  # @return [Boolean]
21
- def ==(other)
22
- self.eql?(other)
21
+ def == other
22
+ eql?(other)
23
23
  end
24
24
 
25
25
  def hash
@@ -13,8 +13,8 @@ module Solargraph
13
13
 
14
14
  # @param pins [Array<Pin::Base>]
15
15
  # @return [Array<Pin::Base>]
16
- def self.combine_method_pins_by_path(pins)
17
- method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method }
16
+ def self.combine_method_pins_by_path pins
17
+ method_pins, alias_pins = pins.partition { |pin| pin.instance_of?(Pin::Method) }
18
18
  by_path = method_pins.group_by(&:path)
19
19
  by_path.transform_values! do |pins|
20
20
  GemPins.combine_method_pins(*pins)
@@ -46,7 +46,7 @@ module Solargraph
46
46
  # @param yard_plugins [Array<String>] The names of YARD plugins to use.
47
47
  # @param gemspec [Gem::Specification]
48
48
  # @return [Array<Pin::Base>]
49
- def self.build_yard_pins(yard_plugins, gemspec)
49
+ def self.build_yard_pins yard_plugins, gemspec
50
50
  Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec)
51
51
  return [] unless Yardoc.cached?(gemspec)
52
52
  yardoc = Yardoc.load!(gemspec)
@@ -57,13 +57,13 @@ module Solargraph
57
57
  # @param rbs_pins [Array<Pin::Base>]
58
58
  #
59
59
  # @return [Array<Pin::Base>]
60
- def self.combine(yard_pins, rbs_pins)
60
+ def self.combine yard_pins, rbs_pins
61
61
  in_yard = Set.new
62
62
  rbs_api_map = Solargraph::ApiMap.new(pins: rbs_pins)
63
63
  combined = yard_pins.map do |yard_pin|
64
64
  in_yard.add yard_pin.path
65
65
  rbs_pin = rbs_api_map.get_path_pins(yard_pin.path).filter { |pin| pin.is_a? Pin::Method }.first
66
- next yard_pin unless rbs_pin && yard_pin.class == Pin::Method
66
+ next yard_pin unless rbs_pin && yard_pin.instance_of?(Pin::Method)
67
67
 
68
68
  unless rbs_pin
69
69
  # @sg-ignore https://github.com/castwide/solargraph/pull/1114
@@ -91,7 +91,7 @@ module Solargraph
91
91
  # @param choices [Array<ComplexType>]
92
92
  # @return [ComplexType]
93
93
  def best_return_type *choices
94
- choices.find { |pin| pin.defined? } || choices.first || ComplexType::UNDEFINED
94
+ choices.find(&:defined?) || choices.first || ComplexType::UNDEFINED
95
95
  end
96
96
  end
97
97
  end
@@ -5,16 +5,16 @@ module Solargraph
5
5
  # The ErrorCode constants for the language server protocol.
6
6
  #
7
7
  module ErrorCodes
8
- PARSE_ERROR = -32700
9
- INVALID_REQUEST = -32600
10
- METHOD_NOT_FOUND = -32601
11
- INVALID_PARAMS = -32602
12
- INTERNAL_ERROR = -32603
13
- SERVER_ERROR_START = -32099
14
- SERVER_ERROR_END = -32000
15
- SERVER_NOT_INITIALIZED = -32002
16
- UNKNOWN_ERROR_CODE = -32001
17
- REQUEST_CANCELLED = -32800
8
+ PARSE_ERROR = -32_700
9
+ INVALID_REQUEST = -32_600
10
+ METHOD_NOT_FOUND = -32_601
11
+ INVALID_PARAMS = -32_602
12
+ INTERNAL_ERROR = -32_603
13
+ SERVER_ERROR_START = -32_099
14
+ SERVER_ERROR_END = -32_000
15
+ SERVER_NOT_INITIALIZED = -32_002
16
+ UNKNOWN_ERROR_CODE = -32_001
17
+ REQUEST_CANCELLED = -32_800
18
18
  end
19
19
  end
20
20
  end
@@ -56,7 +56,7 @@ module Solargraph
56
56
  # @return [void]
57
57
  def tick
58
58
  return if queue.empty? || host.synchronizing?
59
- if !host.options['diagnostics']
59
+ unless host.options['diagnostics']
60
60
  mutex.synchronize { queue.clear }
61
61
  return
62
62
  end
@@ -33,6 +33,7 @@ module Solargraph
33
33
  # @return [void]
34
34
  def update_libraries uri
35
35
  src = sources.find(uri)
36
+ # @sg-ignore Need to add nil check here
36
37
  using = libraries.select { |lib| lib.contain?(src.filename) }
37
38
  using.push library_for(uri) if using.empty?
38
39
  using.each { |lib| lib.merge src }
@@ -44,12 +45,11 @@ module Solargraph
44
45
  # @param uri [String]
45
46
  # @return [Library]
46
47
  def library_for uri
47
- result = explicit_library_for(uri) ||
48
+ explicit_library_for(uri) ||
48
49
  implicit_library_for(uri) ||
49
50
  generic_library_for(uri)
50
51
  # previous library for already call attach. avoid call twice
51
52
  # result.attach sources.find(uri) if sources.include?(uri)
52
- result
53
53
  end
54
54
 
55
55
  # Find an explicit library match for the given URI. An explicit match
@@ -118,8 +118,8 @@ module Solargraph
118
118
  .tap { |lib| lib.add_observer self }
119
119
  end
120
120
 
121
- # @param library [Solargraph::Library]
122
121
  # @param progress [Solargraph::LanguageServer::Progress, nil]
122
+ #
123
123
  # @return [void]
124
124
  def update progress
125
125
  progress&.send(self)