solargraph 0.58.2 → 0.59.0.dev.2

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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +41 -34
  5. data/.github/workflows/rspec.yml +44 -23
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +32 -5
  8. data/.rubocop_todo.yml +50 -966
  9. data/Gemfile +3 -1
  10. data/README.md +3 -3
  11. data/Rakefile +26 -23
  12. data/bin/solargraph +2 -1
  13. data/lib/solargraph/api_map/cache.rb +3 -3
  14. data/lib/solargraph/api_map/constants.rb +13 -3
  15. data/lib/solargraph/api_map/index.rb +23 -18
  16. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  17. data/lib/solargraph/api_map/store.rb +33 -28
  18. data/lib/solargraph/api_map.rb +150 -82
  19. data/lib/solargraph/bench.rb +44 -45
  20. data/lib/solargraph/complex_type/conformance.rb +176 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +28 -17
  22. data/lib/solargraph/complex_type/unique_type.rb +218 -57
  23. data/lib/solargraph/complex_type.rb +170 -57
  24. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  25. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  26. data/lib/solargraph/convention/data_definition.rb +5 -2
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +23 -23
  29. data/lib/solargraph/convention/rakefile.rb +17 -17
  30. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  31. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  32. data/lib/solargraph/convention/struct_definition.rb +8 -4
  33. data/lib/solargraph/convention.rb +78 -78
  34. data/lib/solargraph/converters/dd.rb +19 -17
  35. data/lib/solargraph/converters/dl.rb +17 -15
  36. data/lib/solargraph/converters/dt.rb +17 -15
  37. data/lib/solargraph/converters/misc.rb +3 -1
  38. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  41. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  42. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  43. data/lib/solargraph/doc_map.rb +133 -373
  44. data/lib/solargraph/equality.rb +4 -4
  45. data/lib/solargraph/gem_pins.rb +21 -20
  46. data/lib/solargraph/language_server/error_codes.rb +20 -20
  47. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  48. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  49. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  50. data/lib/solargraph/language_server/host/sources.rb +2 -1
  51. data/lib/solargraph/language_server/host.rb +30 -22
  52. data/lib/solargraph/language_server/message/base.rb +97 -97
  53. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  55. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  56. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  57. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  58. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  59. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  60. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  61. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  62. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  63. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  67. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  68. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  69. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  70. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  71. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  72. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  73. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  74. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  75. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  76. data/lib/solargraph/language_server/message.rb +94 -94
  77. data/lib/solargraph/language_server/request.rb +29 -27
  78. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  79. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  80. data/lib/solargraph/library.rb +85 -44
  81. data/lib/solargraph/location.rb +17 -14
  82. data/lib/solargraph/logging.rb +24 -4
  83. data/lib/solargraph/page.rb +92 -92
  84. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  85. data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
  86. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  87. data/lib/solargraph/parser/node_processor.rb +8 -7
  88. data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
  89. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  90. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  91. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  94. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  95. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
  96. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  97. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  98. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  99. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  100. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  102. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  103. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  104. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  107. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  108. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  109. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  111. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  112. data/lib/solargraph/parser/parser_gem.rb +14 -12
  113. data/lib/solargraph/parser/region.rb +9 -3
  114. data/lib/solargraph/parser/snippet.rb +3 -1
  115. data/lib/solargraph/parser.rb +25 -23
  116. data/lib/solargraph/pin/base.rb +126 -80
  117. data/lib/solargraph/pin/base_variable.rb +273 -24
  118. data/lib/solargraph/pin/block.rb +29 -6
  119. data/lib/solargraph/pin/breakable.rb +7 -1
  120. data/lib/solargraph/pin/callable.rb +65 -21
  121. data/lib/solargraph/pin/closure.rb +7 -10
  122. data/lib/solargraph/pin/common.rb +24 -6
  123. data/lib/solargraph/pin/compound_statement.rb +55 -0
  124. data/lib/solargraph/pin/constant.rb +43 -45
  125. data/lib/solargraph/pin/conversions.rb +10 -4
  126. data/lib/solargraph/pin/delegated_method.rb +19 -8
  127. data/lib/solargraph/pin/documenting.rb +4 -2
  128. data/lib/solargraph/pin/instance_variable.rb +5 -1
  129. data/lib/solargraph/pin/keyword.rb +0 -4
  130. data/lib/solargraph/pin/local_variable.rb +15 -59
  131. data/lib/solargraph/pin/method.rb +153 -104
  132. data/lib/solargraph/pin/method_alias.rb +8 -0
  133. data/lib/solargraph/pin/namespace.rb +19 -12
  134. data/lib/solargraph/pin/parameter.rb +100 -36
  135. data/lib/solargraph/pin/proxy_type.rb +4 -1
  136. data/lib/solargraph/pin/reference/override.rb +1 -1
  137. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  138. data/lib/solargraph/pin/reference.rb +19 -0
  139. data/lib/solargraph/pin/search.rb +3 -2
  140. data/lib/solargraph/pin/signature.rb +15 -12
  141. data/lib/solargraph/pin/symbol.rb +2 -1
  142. data/lib/solargraph/pin/until.rb +2 -4
  143. data/lib/solargraph/pin/while.rb +2 -4
  144. data/lib/solargraph/pin.rb +2 -0
  145. data/lib/solargraph/pin_cache.rb +490 -73
  146. data/lib/solargraph/position.rb +14 -10
  147. data/lib/solargraph/range.rb +16 -15
  148. data/lib/solargraph/rbs_map/conversions.rb +343 -214
  149. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  150. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  151. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  152. data/lib/solargraph/rbs_map.rb +77 -32
  153. data/lib/solargraph/server_methods.rb +16 -16
  154. data/lib/solargraph/shell.rb +128 -73
  155. data/lib/solargraph/source/chain/array.rb +39 -37
  156. data/lib/solargraph/source/chain/call.rb +96 -56
  157. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  158. data/lib/solargraph/source/chain/constant.rb +5 -1
  159. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  160. data/lib/solargraph/source/chain/hash.rb +8 -5
  161. data/lib/solargraph/source/chain/if.rb +12 -10
  162. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  163. data/lib/solargraph/source/chain/link.rb +99 -109
  164. data/lib/solargraph/source/chain/literal.rb +9 -6
  165. data/lib/solargraph/source/chain/or.rb +10 -4
  166. data/lib/solargraph/source/chain/q_call.rb +13 -11
  167. data/lib/solargraph/source/chain/variable.rb +15 -13
  168. data/lib/solargraph/source/chain/z_super.rb +28 -30
  169. data/lib/solargraph/source/chain.rb +49 -38
  170. data/lib/solargraph/source/change.rb +12 -5
  171. data/lib/solargraph/source/cursor.rb +23 -17
  172. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  173. data/lib/solargraph/source/source_chainer.rb +56 -32
  174. data/lib/solargraph/source/updater.rb +5 -1
  175. data/lib/solargraph/source.rb +59 -35
  176. data/lib/solargraph/source_map/clip.rb +48 -29
  177. data/lib/solargraph/source_map/data.rb +4 -1
  178. data/lib/solargraph/source_map/mapper.rb +71 -42
  179. data/lib/solargraph/source_map.rb +21 -9
  180. data/lib/solargraph/type_checker/problem.rb +3 -1
  181. data/lib/solargraph/type_checker/rules.rb +81 -8
  182. data/lib/solargraph/type_checker.rb +195 -120
  183. data/lib/solargraph/version.rb +1 -1
  184. data/lib/solargraph/workspace/config.rb +13 -10
  185. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  186. data/lib/solargraph/workspace/require_paths.rb +1 -0
  187. data/lib/solargraph/workspace.rb +149 -30
  188. data/lib/solargraph/yard_map/helpers.rb +8 -3
  189. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  190. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  191. data/lib/solargraph/yard_map/mapper.rb +13 -8
  192. data/lib/solargraph/yard_tags.rb +20 -20
  193. data/lib/solargraph/yardoc.rb +33 -23
  194. data/lib/solargraph.rb +29 -8
  195. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  196. data/rbs/fills/tuple/tuple.rbs +28 -0
  197. data/rbs/shims/ast/0/node.rbs +1 -1
  198. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  199. data/solargraph.gemspec +36 -34
  200. metadata +38 -33
  201. data/lib/solargraph/type_checker/checks.rb +0 -124
  202. data/lib/solargraph/type_checker/param_def.rb +0 -37
  203. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -19,7 +19,7 @@ module Solargraph
19
19
  @position = Position.normalize(position)
20
20
  end
21
21
 
22
- # @return [String]
22
+ # @return [String, nil]
23
23
  def filename
24
24
  source.filename
25
25
  end
@@ -35,13 +35,17 @@ module Solargraph
35
35
  # The part of the word before the current position. Given the text
36
36
  # `foo.bar`, the start_of_word at position(0, 6) is `ba`.
37
37
  #
38
+ # @sg-ignore Need to add nil check here
38
39
  # @return [String]
39
40
  def start_of_word
40
41
  @start_of_word ||= begin
41
- match = source.code[0..offset-1].to_s.match(start_word_pattern)
42
+ match = source.code[0..(offset - 1)].to_s.match(start_word_pattern)
42
43
  result = (match ? match[0] : '')
43
44
  # Including the preceding colon if the word appears to be a symbol
44
- result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
45
+ # @sg-ignore Need to add nil check here
46
+ if source.code[0..(offset - result.length - 1)].end_with?(':') && !source.code[0..(offset - result.length - 1)].end_with?('::')
47
+ result = ":#{result}"
48
+ end
45
49
  result
46
50
  end
47
51
  end
@@ -50,16 +54,17 @@ module Solargraph
50
54
  # `foo.bar`, the end_of_word at position (0,6) is `r`.
51
55
  #
52
56
  # @return [String]
57
+ # @sg-ignore Need to add nil check here
53
58
  def end_of_word
54
59
  @end_of_word ||= begin
55
- match = source.code[offset..-1].to_s.match(end_word_pattern)
60
+ match = source.code[offset..].to_s.match(end_word_pattern)
56
61
  match ? match[0] : ''
57
62
  end
58
63
  end
59
64
 
60
65
  # @return [Boolean]
61
66
  def start_of_constant?
62
- source.code[offset-2, 2] == '::'
67
+ source.code[offset - 2, 2] == '::'
63
68
  end
64
69
 
65
70
  # The range of the word at the current position.
@@ -110,6 +115,7 @@ module Solargraph
110
115
  def recipient
111
116
  @recipient ||= begin
112
117
  node = recipient_node
118
+ # @sg-ignore Need to add nil check here
113
119
  node ? Cursor.new(source, Range.from_node(node).ending) : nil
114
120
  end
115
121
  end
@@ -122,18 +128,18 @@ module Solargraph
122
128
 
123
129
  # @return [Position]
124
130
  def node_position
125
- @node_position ||= begin
126
- if start_of_word.empty?
127
- match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
128
- if match
129
- Position.from_offset(source.code, offset - match[0].length)
130
- else
131
- position
132
- end
133
- else
134
- position
135
- end
136
- end
131
+ @node_position ||= if start_of_word.empty?
132
+ # @sg-ignore Need to add nil check here
133
+ match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
134
+ if match
135
+ # @sg-ignore Need to add nil check here
136
+ Position.from_offset(source.code, offset - match[0].length)
137
+ else
138
+ position
139
+ end
140
+ else
141
+ position
142
+ end
137
143
  end
138
144
 
139
145
  # @return [Parser::AST::Node, nil]
@@ -10,13 +10,12 @@ module Solargraph
10
10
  # @param string [String]
11
11
  # @return [String]
12
12
  def normalize string
13
- begin
14
- string.dup.force_encoding('UTF-8')
15
- rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
16
- # @todo Improve error handling
17
- Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
- string
19
- end
13
+ string.dup.force_encoding('UTF-8')
14
+ rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError,
15
+ ::Encoding::InvalidByteSequenceError => e
16
+ # @todo Improve error handling
17
+ Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
18
+ string
20
19
  end
21
20
  end
22
21
  end
@@ -32,26 +32,47 @@ module Solargraph
32
32
  # @return [Source::Chain]
33
33
  def chain
34
34
  # Special handling for files that end with an integer and a period
35
- return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
36
- return Chain.new([Chain::Literal.new('Symbol', phrase[1..].to_sym)]) if phrase.start_with?(':') && !phrase.start_with?('::')
37
- return SourceChainer.chain(source, Position.new(position.line, position.character + 1)) if end_of_phrase.strip == '::' && source.code[Position.to_offset(source.code, position)].to_s.match?(/[a-z]/i)
35
+ if phrase =~ /^[0-9]+\.$/
36
+ return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])),
37
+ Chain::UNDEFINED_CALL])
38
+ end
39
+ if phrase.start_with?(':') && !phrase.start_with?('::')
40
+ return Chain.new([Chain::Literal.new('Symbol',
41
+ # @sg-ignore Need to add nil check here
42
+ phrase[1..].to_sym)])
43
+ end
44
+ if end_of_phrase.strip == '::' && source.code[Position.to_offset(
45
+ source.code, position
46
+ )].to_s.match?(/[a-z]/i)
47
+ return SourceChainer.chain(source,
48
+ Position.new(position.line,
49
+ position.character + 1))
50
+ end
38
51
  begin
39
52
  return Chain.new([]) if phrase.end_with?('..')
53
+ # @type [::Parser::AST::Node, nil]
40
54
  node = nil
55
+ # @type [::Parser::AST::Node, nil]
41
56
  parent = nil
42
57
  if !source.repaired? && source.parsed? && source.synchronized?
43
58
  tree = source.tree_at(position.line, position.column)
44
59
  node, parent = tree[0..2]
45
60
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
46
61
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
47
- node = Parser.parse(fixed_phrase) if node.nil?
62
+ # provide filename and line so that we can look up local variables there later
63
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
48
64
  elsif source.repaired?
49
- node = Parser.parse(fixed_phrase)
65
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
50
66
  else
51
- node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
67
+ unless source.error_ranges.any? do |r|
68
+ r.nil? || r.include?(fixed_position)
69
+ end
70
+ node, parent = source.tree_at(fixed_position.line,
71
+ fixed_position.column)[0..2]
72
+ end
52
73
  # Exception for positions that chain literal nodes in unsynchronized sources
53
74
  node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
54
- node = Parser.parse(fixed_phrase) if node.nil?
75
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
55
76
  end
56
77
  rescue Parser::SyntaxError
57
78
  return Chain.new([Chain::UNDEFINED_CALL])
@@ -79,14 +100,16 @@ module Solargraph
79
100
  # @return [Solargraph::Source]
80
101
  attr_reader :source
81
102
 
103
+ # @sg-ignore Need to add nil check here
82
104
  # @return [String]
83
105
  def phrase
84
- @phrase ||= source.code[signature_data..offset-1]
106
+ @phrase ||= source.code[signature_data..(offset - 1)]
85
107
  end
86
108
 
109
+ # @sg-ignore Need to add nil check here
87
110
  # @return [String]
88
111
  def fixed_phrase
89
- @fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
112
+ @fixed_phrase ||= phrase[0..-(end_of_phrase.length + 1)]
90
113
  end
91
114
 
92
115
  # @return [Position]
@@ -95,6 +118,7 @@ module Solargraph
95
118
  end
96
119
 
97
120
  # @return [String]
121
+ # @sg-ignore Need to add nil check here
98
122
  def end_of_phrase
99
123
  @end_of_phrase ||= begin
100
124
  match = phrase.match(/\s*(\.{1}|::)\s*$/)
@@ -137,47 +161,47 @@ module Solargraph
137
161
  brackets = 0
138
162
  squares = 0
139
163
  parens = 0
140
- index -=1
164
+ index -= 1
141
165
  in_whitespace = false
142
166
  while index >= 0
143
167
  pos = Position.from_offset(@source.code, index)
144
- break if index > 0 and @source.comment_at?(pos)
145
- break if brackets > 0 or parens > 0 or squares > 0
168
+ break if index.positive? && @source.comment_at?(pos)
169
+ break if brackets.positive? || parens.positive? || squares.positive?
146
170
  char = @source.code[index, 1]
147
171
  break if char.nil? # @todo Is this the right way to handle this?
148
- if brackets.zero? and parens.zero? and squares.zero? and [' ', "\r", "\n", "\t"].include?(char)
172
+ if brackets.zero? && parens.zero? && squares.zero? && [' ', "\r", "\n", "\t"].include?(char)
149
173
  in_whitespace = true
150
174
  else
151
- if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
152
- unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
153
- old = @source.code[index+1..-1]
154
- nxt = @source.code[index+1..-1].lstrip
155
- index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
156
- break
157
- end
175
+ # @sg-ignore Need to add nil check here
176
+ if brackets.zero? && parens.zero? && squares.zero? && in_whitespace && !((char == '.') || @source.code[(index + 1)..].strip.start_with?('.'))
177
+ @source.code[(index + 1)..]
178
+ # @sg-ignore Need to add nil check here
179
+ @source.code[(index + 1)..].lstrip
180
+ # @sg-ignore Need to add nil check here
181
+ index += (@source.code[(index + 1)..].length - @source.code[(index + 1)..].lstrip.length)
182
+ break
158
183
  end
159
- if char == ')'
160
- parens -=1
161
- elsif char == ']'
162
- squares -=1
163
- elsif char == '}'
184
+ case char
185
+ when ')'
186
+ parens -= 1
187
+ when ']'
188
+ squares -= 1
189
+ when '}'
164
190
  brackets -= 1
165
- elsif char == '('
191
+ when '('
166
192
  parens += 1
167
- elsif char == '{'
193
+ when '{'
168
194
  brackets += 1
169
- elsif char == '['
195
+ when '['
170
196
  squares += 1
171
197
  end
172
- if brackets.zero? and parens.zero? and squares.zero?
198
+ if brackets.zero? && parens.zero? && squares.zero?
173
199
  break if ['"', "'", ',', ';', '%'].include?(char)
174
200
  break if ['!', '?'].include?(char) && index < offset - 1
175
201
  break if char == '$'
176
202
  if char == '@'
177
203
  index -= 1
178
- if @source.code[index, 1] == '@'
179
- index -= 1
180
- end
204
+ index -= 1 if @source.code[index, 1] == '@'
181
205
  break
182
206
  end
183
207
  elsif parens == 1 || brackets == 1 || squares == 1
@@ -29,14 +29,18 @@ module Solargraph
29
29
 
30
30
  # @param text [String]
31
31
  # @param nullable [Boolean]
32
+ # @sg-ignore changes doesn't mutate @output, so this can never be nil
32
33
  # @return [String]
33
34
  def write text, nullable = false
34
35
  can_nullify = (nullable and changes.length == 1)
35
- return @output if @input == text and can_nullify == @did_nullify
36
+ return @output if (@input == text) && (can_nullify == @did_nullify)
36
37
  @input = text
37
38
  @output = text
38
39
  @did_nullify = can_nullify
39
40
  changes.each do |ch|
41
+ # @sg-ignore Wrong argument type for
42
+ # Solargraph::Source::Change#write: text expected String,
43
+ # received String, nil
40
44
  @output = ch.write(@output, can_nullify)
41
45
  end
42
46
  @output
@@ -60,11 +60,13 @@ module Solargraph
60
60
  # @param c1 [Integer]
61
61
  # @param l2 [Integer]
62
62
  # @param c2 [Integer]
63
+ #
64
+ # @sg-ignore Need to add nil check here
63
65
  # @return [String]
64
66
  def from_to l1, c1, l2, c2
65
67
  b = Solargraph::Position.line_char_to_offset(code, l1, c1)
66
68
  e = Solargraph::Position.line_char_to_offset(code, l2, c2)
67
- code[b..e-1]
69
+ code[b..(e - 1)]
68
70
  end
69
71
 
70
72
  # Get the nearest node that contains the specified index.
@@ -72,7 +74,7 @@ module Solargraph
72
74
  # @param line [Integer]
73
75
  # @param column [Integer]
74
76
  # @return [AST::Node]
75
- def node_at(line, column)
77
+ def node_at line, column
76
78
  tree_at(line, column).first
77
79
  end
78
80
 
@@ -81,8 +83,8 @@ module Solargraph
81
83
  #
82
84
  # @param line [Integer]
83
85
  # @param column [Integer]
84
- # @return [Array<AST::Node>]
85
- def tree_at(line, column)
86
+ # @return [Array<Parser::AST::Node>]
87
+ def tree_at line, column
86
88
  position = Position.new(line, column)
87
89
  stack = []
88
90
  inner_tree_at node, position, stack
@@ -131,20 +133,29 @@ module Solargraph
131
133
  return false if Position.to_offset(code, position) >= code.length
132
134
  string_nodes.each do |node|
133
135
  range = Range.from_node(node)
136
+ # @sg-ignore Need to add nil check here
134
137
  next if range.ending.line < position.line
138
+ # @sg-ignore Need to add nil check here
135
139
  break if range.ending.line > position.line
140
+ # @sg-ignore Need to add nil check here
136
141
  return true if node.type == :str && range.include?(position) && range.start != position
137
- return true if [:STR, :str].include?(node.type) && range.include?(position) && range.start != position
142
+ # @sg-ignore Need to add nil check here
143
+ return true if %i[STR str].include?(node.type) && range.include?(position) && range.start != position
138
144
  if node.type == :dstr
139
145
  inner = node_at(position.line, position.column)
140
146
  next if inner.nil?
141
147
  inner_range = Range.from_node(inner)
148
+ # @sg-ignore Need to add nil check here
142
149
  next unless range.include?(inner_range.ending)
143
150
  return true if inner.type == :str
151
+ # @sg-ignore Need to add nil check here
144
152
  inner_code = at(Solargraph::Range.new(inner_range.start, position))
145
- return true if (inner.type == :dstr && inner_range.ending.character <= position.character) && !inner_code.end_with?('}') ||
153
+ # @sg-ignore Need to add nil check here
154
+ return true if (inner.type == :dstr && inner_range.ending.character <= position.character && !inner_code.end_with?('}')) ||
155
+ # @sg-ignore Need to add nil check here
146
156
  (inner.type != :dstr && inner_range.ending.line == position.line && position.character <= inner_range.ending.character && inner_code.end_with?('}'))
147
157
  end
158
+ # @sg-ignore Need to add nil check here
148
159
  break if range.ending.line > position.line
149
160
  end
150
161
  false
@@ -160,7 +171,7 @@ module Solargraph
160
171
  def comment_at? position
161
172
  comment_ranges.each do |range|
162
173
  return true if range.include?(position) ||
163
- (range.ending.line == position.line && range.ending.column < position.column)
174
+ (range.ending.line == position.line && range.ending.column < position.column)
164
175
  break if range.ending.line > position.line
165
176
  end
166
177
  false
@@ -179,19 +190,24 @@ module Solargraph
179
190
 
180
191
  # @param node [Parser::AST::Node]
181
192
  # @return [String]
182
- def code_for(node)
193
+ def code_for node
183
194
  rng = Range.from_node(node)
195
+ # @sg-ignore Need to add nil check here
184
196
  b = Position.line_char_to_offset(code, rng.start.line, rng.start.column)
197
+ # @sg-ignore Need to add nil check here
185
198
  e = Position.line_char_to_offset(code, rng.ending.line, rng.ending.column)
186
- frag = code[b..e-1].to_s
199
+ frag = code[b..(e - 1)].to_s
187
200
  frag.strip.gsub(/,$/, '')
188
201
  end
189
202
 
190
- # @param node [Parser::AST::Node]
203
+ # @param node [AST::Node]
204
+ #
191
205
  # @return [String, nil]
192
206
  def comments_for node
193
207
  rng = Range.from_node(node)
208
+ # @sg-ignore Need to add nil check here
194
209
  stringified_comments[rng.start.line] ||= begin
210
+ # @sg-ignore Need to add nil check here
195
211
  buff = associated_comments[rng.start.line]
196
212
  buff ? stringify_comment_array(buff) : nil
197
213
  end
@@ -208,8 +224,8 @@ module Solargraph
208
224
  end
209
225
 
210
226
  FOLDING_NODE_TYPES = %i[
211
- class sclass module def defs if str dstr array while unless kwbegin hash block
212
- ].freeze
227
+ class sclass module def defs if str dstr array while unless kwbegin hash block
228
+ ].freeze
213
229
 
214
230
  # Get an array of ranges that can be folded, e.g., the range of a class
215
231
  # definition or an if condition.
@@ -219,6 +235,7 @@ module Solargraph
219
235
  # @return [Array<Range>]
220
236
  def folding_ranges
221
237
  @folding_ranges ||= begin
238
+ # @type [Array<Range>]
222
239
  result = []
223
240
  inner_folding_ranges node, result
224
241
  result.concat foldable_comment_block_ranges
@@ -232,7 +249,7 @@ module Solargraph
232
249
 
233
250
  # Get a hash of comments grouped by the line numbers of the associated code.
234
251
  #
235
- # @return [Hash{Integer => String}]
252
+ # @return [Hash{Integer => String, nil}]
236
253
  def associated_comments
237
254
  @associated_comments ||= begin
238
255
  # @type [Hash{Integer => String}]
@@ -265,18 +282,22 @@ module Solargraph
265
282
  cursor
266
283
  end
267
284
 
268
- # @param top [Parser::AST::Node]
285
+ # @param top [Parser::AST::Node, nil]
269
286
  # @param result [Array<Range>]
270
287
  # @param parent [Symbol, nil]
271
288
  # @return [void]
272
289
  def inner_folding_ranges top, result = [], parent = nil
273
290
  return unless Parser.is_ast_node?(top)
291
+ # @sg-ignore Translate to something flow sensitive typing understands
274
292
  if FOLDING_NODE_TYPES.include?(top.type)
293
+ # @sg-ignore Translate to something flow sensitive typing understands
275
294
  range = Range.from_node(top)
276
- if result.empty? || range.start.line > result.last.start.line
277
- result.push range unless range.ending.line - range.start.line < 2
295
+ # @sg-ignore Need to add nil check here
296
+ if (result.empty? || range.start.line > result.last.start.line) && range.ending.line - range.start.line >= 2
297
+ result.push range
278
298
  end
279
299
  end
300
+ # @sg-ignore Translate to something flow sensitive typing understands
280
301
  top.children.each do |child|
281
302
  inner_folding_ranges(child, result, top.type)
282
303
  end
@@ -290,7 +311,7 @@ module Solargraph
290
311
  ctxt = String.new('')
291
312
  started = false
292
313
  skip = nil
293
- comments.lines.each { |l|
314
+ comments.lines.each do |l|
294
315
  # Trim the comment and minimum leading whitespace
295
316
  p = l.force_encoding('UTF-8').encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
296
317
  if p.strip.empty?
@@ -298,17 +319,18 @@ module Solargraph
298
319
  ctxt.concat p
299
320
  else
300
321
  here = p.index(/[^ \t]/)
322
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
301
323
  skip = here if skip.nil? || here < skip
302
- ctxt.concat p[skip..-1]
324
+ ctxt.concat p[skip..]
303
325
  end
304
326
  started = true
305
- }
327
+ end
306
328
  ctxt
307
329
  end
308
330
 
309
331
  # A hash of line numbers and their associated comments.
310
332
  #
311
- # @return [Hash{Integer => Array<String>, nil}]
333
+ # @return [Hash{Integer => String}]
312
334
  def stringified_comments
313
335
  @stringified_comments ||= {}
314
336
  end
@@ -331,7 +353,7 @@ module Solargraph
331
353
  return [] unless synchronized?
332
354
  result = []
333
355
  grouped = []
334
- comments.keys.each do |l|
356
+ comments.each_key do |l|
335
357
  if grouped.empty? || l == grouped.last + 1
336
358
  grouped.push l
337
359
  else
@@ -348,10 +370,12 @@ module Solargraph
348
370
  def string_nodes_in n
349
371
  result = []
350
372
  if Parser.is_ast_node?(n)
351
- if n.type == :str || n.type == :dstr || n.type == :STR || n.type == :DSTR
373
+ # @sg-ignore Translate to something flow sensitive typing understands
374
+ if %i[str dstr STR DSTR].include?(n.type)
352
375
  result.push n
353
376
  else
354
- n.children.each{ |c| result.concat string_nodes_in(c) }
377
+ # @sg-ignore Translate to something flow sensitive typing understands
378
+ n.children.each { |c| result.concat string_nodes_in(c) }
355
379
  end
356
380
  end
357
381
  result
@@ -364,13 +388,13 @@ module Solargraph
364
388
  def inner_tree_at node, position, stack
365
389
  return if node.nil?
366
390
  here = Range.from_node(node)
367
- if here.contain?(position)
368
- stack.unshift node
369
- node.children.each do |c|
370
- next unless Parser.is_ast_node?(c)
371
- next if c.loc.expression.nil?
372
- inner_tree_at(c, position, stack)
373
- end
391
+ # @sg-ignore Need to add nil check here
392
+ return unless here.contain?(position)
393
+ stack.unshift node
394
+ node.children.each do |c|
395
+ next unless Parser.is_ast_node?(c)
396
+ next if c.loc.expression.nil?
397
+ inner_tree_at(c, position, stack)
374
398
  end
375
399
  end
376
400
 
@@ -396,10 +420,10 @@ module Solargraph
396
420
  end
397
421
  @finalized = true
398
422
  begin
399
- @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
423
+ @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename, 0)
400
424
  @parsed = true
401
425
  @repaired = @code
402
- rescue Parser::SyntaxError, EncodingError => e
426
+ rescue Parser::SyntaxError, EncodingError
403
427
  @node = nil
404
428
  @comments = {}
405
429
  @parsed = false
@@ -412,9 +436,9 @@ module Solargraph
412
436
  end
413
437
  error_ranges.concat(changes.map(&:range))
414
438
  begin
415
- @node, @comments = Solargraph::Parser.parse_with_comments(@repaired, filename)
439
+ @node, @comments = Solargraph::Parser.parse_with_comments(@repaired, filename, 0)
416
440
  @parsed = true
417
- rescue Parser::SyntaxError, EncodingError => e
441
+ rescue Parser::SyntaxError, EncodingError
418
442
  @node = nil
419
443
  @comments = {}
420
444
  @parsed = false
@@ -427,7 +451,7 @@ module Solargraph
427
451
 
428
452
  # @param val [String]
429
453
  # @return [String]
430
- def code=(val)
454
+ def code= val
431
455
  @code_lines = nil
432
456
  @finalized = false
433
457
  @code = val