solargraph 0.58.2 → 0.59.0.dev.1

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 (154) 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 +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -7,13 +7,13 @@ module Solargraph
7
7
  class Change
8
8
  include EncodingFixes
9
9
 
10
- # @return [Range]
10
+ # @return [Range, nil]
11
11
  attr_reader :range
12
12
 
13
13
  # @return [String]
14
14
  attr_reader :new_text
15
15
 
16
- # @param range [Range] The starting and ending positions of the change.
16
+ # @param range [Range, nil] The starting and ending positions of the change.
17
17
  # If nil, the original text will be overwritten.
18
18
  # @param new_text [String] The text to be changed.
19
19
  def initialize range, new_text
@@ -31,9 +31,11 @@ module Solargraph
31
31
  if nullable and !range.nil? and new_text.match(/[.\[{(@$:]$/)
32
32
  [':', '@'].each do |dupable|
33
33
  next unless new_text == dupable
34
+ # @sg-ignore flow sensitive typing needs to handle attrs
34
35
  offset = Position.to_offset(text, range.start)
35
36
  if text[offset - 1] == dupable
36
37
  p = Position.from_offset(text, offset - 1)
38
+ # @sg-ignore flow sensitive typing needs to handle attrs
37
39
  r = Change.new(Range.new(p, range.start), ' ')
38
40
  text = r.write(text)
39
41
  end
@@ -58,9 +60,12 @@ module Solargraph
58
60
  fixed
59
61
  else
60
62
  result = commit text, fixed
63
+ # @sg-ignore flow sensitive typing needs to handle attrs
61
64
  off = Position.to_offset(text, range.start)
65
+ # @sg-ignore Need to add nil check here
62
66
  match = result[0, off].match(/[.:]+\z/)
63
67
  if match
68
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
64
69
  result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
65
70
  end
66
71
  result
@@ -73,7 +78,9 @@ module Solargraph
73
78
  # @param insert [String]
74
79
  # @return [String]
75
80
  def commit text, insert
81
+ # @sg-ignore Need to add nil check here
76
82
  start_offset = Position.to_offset(text, range.start)
83
+ # @sg-ignore Need to add nil check here
77
84
  end_offset = Position.to_offset(text, range.ending)
78
85
  (start_offset == 0 ? '' : text[0..start_offset-1].to_s) + normalize(insert) + text[end_offset..-1].to_s
79
86
  end
@@ -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,12 +35,14 @@ 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
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
45
+ # @sg-ignore Need to add nil check here
44
46
  result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
45
47
  result
46
48
  end
@@ -50,6 +52,7 @@ module Solargraph
50
52
  # `foo.bar`, the end_of_word at position (0,6) is `r`.
51
53
  #
52
54
  # @return [String]
55
+ # @sg-ignore Need to add nil check here
53
56
  def end_of_word
54
57
  @end_of_word ||= begin
55
58
  match = source.code[offset..-1].to_s.match(end_word_pattern)
@@ -110,6 +113,7 @@ module Solargraph
110
113
  def recipient
111
114
  @recipient ||= begin
112
115
  node = recipient_node
116
+ # @sg-ignore Need to add nil check here
113
117
  node ? Cursor.new(source, Range.from_node(node).ending) : nil
114
118
  end
115
119
  end
@@ -124,8 +128,10 @@ module Solargraph
124
128
  def node_position
125
129
  @node_position ||= begin
126
130
  if start_of_word.empty?
131
+ # @sg-ignore Need to add nil check here
127
132
  match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
128
133
  if match
134
+ # @sg-ignore Need to add nil check here
129
135
  Position.from_offset(source.code, offset - match[0].length)
130
136
  else
131
137
  position
@@ -33,25 +33,29 @@ module Solargraph
33
33
  def chain
34
34
  # Special handling for files that end with an integer and a period
35
35
  return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
36
+ # @sg-ignore Need to add nil check here
36
37
  return Chain.new([Chain::Literal.new('Symbol', phrase[1..].to_sym)]) if phrase.start_with?(':') && !phrase.start_with?('::')
37
38
  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)
38
39
  begin
39
40
  return Chain.new([]) if phrase.end_with?('..')
41
+ # @type [::Parser::AST::Node, nil]
40
42
  node = nil
43
+ # @type [::Parser::AST::Node, nil]
41
44
  parent = nil
42
45
  if !source.repaired? && source.parsed? && source.synchronized?
43
46
  tree = source.tree_at(position.line, position.column)
44
47
  node, parent = tree[0..2]
45
48
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
46
49
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
47
- node = Parser.parse(fixed_phrase) if node.nil?
50
+ # provide filename and line so that we can look up local variables there later
51
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
48
52
  elsif source.repaired?
49
- node = Parser.parse(fixed_phrase)
53
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
50
54
  else
51
55
  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)}
52
56
  # Exception for positions that chain literal nodes in unsynchronized sources
53
57
  node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
54
- node = Parser.parse(fixed_phrase) if node.nil?
58
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
55
59
  end
56
60
  rescue Parser::SyntaxError
57
61
  return Chain.new([Chain::UNDEFINED_CALL])
@@ -79,11 +83,13 @@ module Solargraph
79
83
  # @return [Solargraph::Source]
80
84
  attr_reader :source
81
85
 
86
+ # @sg-ignore Need to add nil check here
82
87
  # @return [String]
83
88
  def phrase
84
89
  @phrase ||= source.code[signature_data..offset-1]
85
90
  end
86
91
 
92
+ # @sg-ignore Need to add nil check here
87
93
  # @return [String]
88
94
  def fixed_phrase
89
95
  @fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
@@ -95,6 +101,7 @@ module Solargraph
95
101
  end
96
102
 
97
103
  # @return [String]
104
+ # @sg-ignore Need to add nil check here
98
105
  def end_of_phrase
99
106
  @end_of_phrase ||= begin
100
107
  match = phrase.match(/\s*(\.{1}|::)\s*$/)
@@ -149,9 +156,12 @@ module Solargraph
149
156
  in_whitespace = true
150
157
  else
151
158
  if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
159
+ # @sg-ignore Need to add nil check here
152
160
  unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
153
161
  old = @source.code[index+1..-1]
162
+ # @sg-ignore Need to add nil check here
154
163
  nxt = @source.code[index+1..-1].lstrip
164
+ # @sg-ignore Need to add nil check here
155
165
  index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
156
166
  break
157
167
  end
@@ -29,6 +29,7 @@ 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)
@@ -37,6 +38,9 @@ module Solargraph
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,6 +60,8 @@ 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)
@@ -81,7 +83,7 @@ module Solargraph
81
83
  #
82
84
  # @param line [Integer]
83
85
  # @param column [Integer]
84
- # @return [Array<AST::Node>]
86
+ # @return [Array<Parser::AST::Node>]
85
87
  def tree_at(line, column)
86
88
  position = Position.new(line, column)
87
89
  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
142
+ # @sg-ignore Need to add nil check here
137
143
  return true if [: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))
153
+ # @sg-ignore Need to add nil check here
145
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
@@ -181,17 +192,22 @@ module Solargraph
181
192
  # @return [String]
182
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
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
@@ -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,23 @@ 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)
295
+ # @sg-ignore Need to add nil check here
276
296
  if result.empty? || range.start.line > result.last.start.line
297
+ # @sg-ignore Need to add nil check here
277
298
  result.push range unless range.ending.line - range.start.line < 2
278
299
  end
279
300
  end
301
+ # @sg-ignore Translate to something flow sensitive typing understands
280
302
  top.children.each do |child|
281
303
  inner_folding_ranges(child, result, top.type)
282
304
  end
@@ -298,6 +320,7 @@ module Solargraph
298
320
  ctxt.concat p
299
321
  else
300
322
  here = p.index(/[^ \t]/)
323
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
301
324
  skip = here if skip.nil? || here < skip
302
325
  ctxt.concat p[skip..-1]
303
326
  end
@@ -308,7 +331,7 @@ module Solargraph
308
331
 
309
332
  # A hash of line numbers and their associated comments.
310
333
  #
311
- # @return [Hash{Integer => Array<String>, nil}]
334
+ # @return [Hash{Integer => String}]
312
335
  def stringified_comments
313
336
  @stringified_comments ||= {}
314
337
  end
@@ -348,9 +371,11 @@ module Solargraph
348
371
  def string_nodes_in n
349
372
  result = []
350
373
  if Parser.is_ast_node?(n)
374
+ # @sg-ignore Translate to something flow sensitive typing understands
351
375
  if n.type == :str || n.type == :dstr || n.type == :STR || n.type == :DSTR
352
376
  result.push n
353
377
  else
378
+ # @sg-ignore Translate to something flow sensitive typing understands
354
379
  n.children.each{ |c| result.concat string_nodes_in(c) }
355
380
  end
356
381
  end
@@ -364,6 +389,7 @@ module Solargraph
364
389
  def inner_tree_at node, position, stack
365
390
  return if node.nil?
366
391
  here = Range.from_node(node)
392
+ # @sg-ignore Need to add nil check here
367
393
  if here.contain?(position)
368
394
  stack.unshift node
369
395
  node.children.each do |c|
@@ -396,7 +422,7 @@ module Solargraph
396
422
  end
397
423
  @finalized = true
398
424
  begin
399
- @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
425
+ @node, @comments = Solargraph::Parser.parse_with_comments(@code, filename, 0)
400
426
  @parsed = true
401
427
  @repaired = @code
402
428
  rescue Parser::SyntaxError, EncodingError => e
@@ -412,7 +438,7 @@ module Solargraph
412
438
  end
413
439
  error_ranges.concat(changes.map(&:range))
414
440
  begin
415
- @node, @comments = Solargraph::Parser.parse_with_comments(@repaired, filename)
441
+ @node, @comments = Solargraph::Parser.parse_with_comments(@repaired, filename, 0)
416
442
  @parsed = true
417
443
  rescue Parser::SyntaxError, EncodingError => e
418
444
  @node = nil
@@ -12,6 +12,7 @@ module Solargraph
12
12
  @api_map = api_map
13
13
  @cursor = cursor
14
14
  closure_pin = closure
15
+ # @sg-ignore Need to add nil check here
15
16
  closure_pin.rebind(api_map) if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver).contain?(cursor.range.start)
16
17
  end
17
18
 
@@ -20,6 +21,7 @@ module Solargraph
20
21
  return [] if cursor.comment? || cursor.chain.literal?
21
22
  result = cursor.chain.define(api_map, closure, locals)
22
23
  result.concat file_global_methods
24
+ # @sg-ignore Need to add nil check here
23
25
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
24
26
  result
25
27
  end
@@ -78,7 +80,7 @@ module Solargraph
78
80
  # @param phrase [String]
79
81
  # @return [Array<Solargraph::Pin::Base>]
80
82
  def translate phrase
81
- chain = Parser.chain(Parser.parse(phrase))
83
+ chain = Parser.chain(Parser.parse(phrase, cursor.filename, cursor.position.line))
82
84
  chain.define(api_map, closure, locals)
83
85
  end
84
86
 
@@ -92,6 +94,7 @@ module Solargraph
92
94
 
93
95
  # @return [SourceMap]
94
96
  def source_map
97
+ # @sg-ignore Need to add nil check here
95
98
  @source_map ||= api_map.source_map(cursor.filename)
96
99
  end
97
100
 
@@ -150,16 +153,23 @@ module Solargraph
150
153
  # @return [Completion]
151
154
  def tag_complete
152
155
  result = []
156
+ # @sg-ignore Need to add nil check here
153
157
  match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
154
158
  if match
159
+ # @sg-ignore Need to add nil check here
155
160
  full = match[1]
161
+ # @sg-ignore Need to add nil check here
156
162
  if full.include?('::')
163
+ # @sg-ignore Need to add nil check here
157
164
  if full.end_with?('::')
165
+ # @sg-ignore Need to add nil check here
158
166
  result.concat api_map.get_constants(full[0..-3], *gates)
159
167
  else
168
+ # @sg-ignore Need to add nil check here
160
169
  result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
161
170
  end
162
171
  else
172
+ # @sg-ignore Need to add nil check here
163
173
  result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
164
174
  end
165
175
  end
@@ -176,6 +186,7 @@ module Solargraph
176
186
  cursor.chain.base.infer(api_map, context_pin, locals)
177
187
  else
178
188
  if full.include?('::') && cursor.chain.links.length == 1
189
+ # @sg-ignore Need to add nil check here
179
190
  ComplexType.try_parse(full.split('::')[0..-2].join('::'))
180
191
  elsif cursor.chain.links.length > 1
181
192
  ComplexType.try_parse(full)
@@ -199,7 +210,7 @@ module Solargraph
199
210
  if cursor.word.start_with?('@@')
200
211
  return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
201
212
  elsif cursor.word.start_with?('@')
202
- return package_completions(api_map.get_instance_variable_pins(closure.binder.namespace, closure.binder.scope))
213
+ return package_completions(api_map.get_instance_variable_pins(closure.full_context.namespace, closure.context.scope))
203
214
  elsif cursor.word.start_with?('$')
204
215
  return package_completions(api_map.get_global_variable_pins)
205
216
  end
@@ -8,13 +8,16 @@ module Solargraph
8
8
  @source = source
9
9
  end
10
10
 
11
+ # @sg-ignore Translate to something flow sensitive typing understands
11
12
  # @return [Array<Solargraph::Pin::Base>]
13
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1100
12
14
  def pins
13
15
  generate
14
16
  @pins || []
15
17
  end
16
18
 
17
- # @return [Array<Solargraph::LocalVariable>]
19
+ # @sg-ignore Translate to something flow sensitive typing understands
20
+ # @return [Array<Solargraph::Pin::LocalVariable>]
18
21
  def locals
19
22
  generate
20
23
  @locals || []
@@ -24,6 +24,7 @@ module Solargraph
24
24
  @code = source.code
25
25
  @comments = source.comments
26
26
  @pins, @locals = Parser.map(source)
27
+ # @param p [Solargraph::Pin::Base]
27
28
  @pins.each { |p| p.source = :code }
28
29
  @locals.each { |l| l.source = :code }
29
30
  process_comment_directives
@@ -48,6 +49,7 @@ module Solargraph
48
49
  # @param source [Source]
49
50
  # @return [Array]
50
51
  def map source
52
+ # @sg-ignore Need to add nil check here
51
53
  return new.unmap(source.filename, source.code) unless source.parsed?
52
54
  new.map source
53
55
  end
@@ -62,6 +64,7 @@ module Solargraph
62
64
  # @param position [Solargraph::Position]
63
65
  # @return [Solargraph::Pin::Closure]
64
66
  def closure_at(position)
67
+ # @sg-ignore Need to add nil check here
65
68
  pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
66
69
  end
67
70
 
@@ -90,11 +93,13 @@ module Solargraph
90
93
  def find_directive_line_number comment, tag, start
91
94
  # Avoid overruning the index
92
95
  return start unless start < comment.lines.length
96
+ # @sg-ignore Need to add nil check here
93
97
  num = comment.lines[start..-1].find_index do |line|
94
98
  # Legacy method directives might be `@method` instead of `@!method`
95
99
  # @todo Legacy syntax should probably emit a warning
96
100
  line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
97
101
  end
102
+ # @sg-ignore Need to add nil check here
98
103
  num.to_i + start
99
104
  end
100
105
 
@@ -103,17 +108,21 @@ module Solargraph
103
108
  # @param directive [YARD::Tags::Directive]
104
109
  # @return [void]
105
110
  def process_directive source_position, comment_position, directive
111
+ # @sg-ignore Need to add nil check here
106
112
  docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
107
113
  location = Location.new(@filename, Range.new(comment_position, comment_position))
108
114
  case directive.tag.tag_name
109
115
  when 'method'
110
116
  namespace = closure_at(source_position) || @pins.first
117
+ # @todo Missed nil violation
118
+ # @todo Need to add nil check here
111
119
  if namespace.location.range.start.line < comment_position.line
112
120
  namespace = closure_at(comment_position)
113
121
  end
114
122
  begin
115
123
  src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
116
124
  region = Parser::Region.new(source: src, closure: namespace)
125
+ # @type [Array<Pin::Method>]
117
126
  method_gen_pins = Parser.process_node(src.node, region).first.select { |pin| pin.is_a?(Pin::Method) }
118
127
  gen_pin = method_gen_pins.last
119
128
  return if gen_pin.nil?
@@ -165,10 +174,13 @@ module Solargraph
165
174
  when 'visibility'
166
175
 
167
176
  kind = directive.tag.text&.to_sym
177
+ # @sg-ignore Need to look at Tuple#include? handling
168
178
  return unless [:private, :protected, :public].include?(kind)
169
179
 
170
180
  name = directive.tag.name
171
181
  closure = closure_at(source_position) || @pins.first
182
+ # @todo Missed nil violation
183
+ # @todo Need to add nil check here
172
184
  if closure.location.range.start.line < comment_position.line
173
185
  closure = closure_at(comment_position)
174
186
  end
@@ -186,6 +198,7 @@ module Solargraph
186
198
  when 'parse'
187
199
  begin
188
200
  ns = closure_at(source_position)
201
+ # @sg-ignore Need to add nil check here
189
202
  src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
190
203
  region = Parser::Region.new(source: src, closure: ns)
191
204
  # @todo These pins may need to be marked not explicit
@@ -195,7 +208,11 @@ module Solargraph
195
208
  else
196
209
  comment_position.line
197
210
  end
198
- Parser.process_node(src.node, region, @pins)
211
+ locals = []
212
+ ivars = []
213
+ Parser.process_node(src.node, region, @pins, locals, ivars)
214
+ @pins.concat ivars
215
+ # @sg-ignore Need to add nil check here
199
216
  @pins[index..-1].each do |p|
200
217
  # @todo Smelly instance variable access
201
218
  p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
@@ -206,8 +223,10 @@ module Solargraph
206
223
  end
207
224
  when 'domain'
208
225
  namespace = closure_at(source_position) || Pin::ROOT_PIN
226
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
209
227
  namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
210
228
  when 'override'
229
+ # @sg-ignore Need to add nil check here
211
230
  pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags,
212
231
  source: :source_map)
213
232
  when 'macro'
@@ -217,7 +236,9 @@ module Solargraph
217
236
 
218
237
  # @param line1 [Integer]
219
238
  # @param line2 [Integer]
239
+ # @sg-ignore Need to add nil check here
220
240
  def no_empty_lines?(line1, line2)
241
+ # @sg-ignore Need to add nil check here
221
242
  @code.lines[line1..line2].none? { |line| line.strip.empty? }
222
243
  end
223
244
 
@@ -235,6 +256,7 @@ module Solargraph
235
256
  started = true
236
257
  elsif started && !p.strip.empty?
237
258
  cur = p.index(/[^ ]/)
259
+ # @sg-ignore Need to add nil check here
238
260
  num = cur if cur < num
239
261
  end
240
262
  ctxt += "#{p[num..-1]}" if started
@@ -248,6 +270,7 @@ module Solargraph
248
270
  code_lines = @code.lines
249
271
  @source.associated_comments.each do |line, comments|
250
272
  src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
273
+ # @sg-ignore Need to add nil check here
251
274
  com_pos = Position.new(line + 1 - comments.lines.length, 0)
252
275
  process_comment(src_pos, com_pos, comments)
253
276
  end
@@ -34,6 +34,8 @@ module Solargraph
34
34
  # @param source [Source]
35
35
  def initialize source
36
36
  @source = source
37
+ # @type [Array<Pin::Base>, nil]
38
+ @convention_pins = nil
37
39
 
38
40
  conventions_environ.merge Convention.for_local(self) unless filename.nil?
39
41
  # FIXME: unmemoizing the document_symbols in case it was called and memoized from any of conventions above
@@ -63,7 +65,7 @@ module Solargraph
63
65
  @api_hash ||= (pins_by_class(Pin::Constant) + pins_by_class(Pin::Namespace).select { |pin| pin.namespace.to_s > '' } + pins_by_class(Pin::Reference) + pins_by_class(Pin::Method).map(&:node) + locals).hash
64
66
  end
65
67
 
66
- # @return [String]
68
+ # @return [String, nil]
67
69
  def filename
68
70
  source.filename
69
71
  end
@@ -84,6 +86,7 @@ module Solargraph
84
86
  end
85
87
 
86
88
  # all pins except Solargraph::Pin::Reference::Reference
89
+ #
87
90
  # @return [Array<Pin::Base>]
88
91
  def document_symbols
89
92
  @document_symbols ||= (pins + convention_pins).select do |pin|
@@ -97,7 +100,7 @@ module Solargraph
97
100
  Pin::Search.new(document_symbols, query).results
98
101
  end
99
102
 
100
- # @param position [Position]
103
+ # @param position [Position, Array(Integer, Integer)]
101
104
  # @return [Source::Cursor]
102
105
  def cursor_at position
103
106
  Source::Cursor.new(source, position)
@@ -125,7 +128,7 @@ module Solargraph
125
128
 
126
129
  # @param line [Integer]
127
130
  # @param character [Integer]
128
- # @return [Pin::Namespace,Pin::Method,Pin::Block]
131
+ # @return [Pin::Closure]
129
132
  def locate_closure_pin line, character
130
133
  _locate_pin line, character, Pin::Closure
131
134
  end
@@ -143,7 +146,7 @@ module Solargraph
143
146
  # @return [Array<Pin::LocalVariable>]
144
147
  def locals_at(location)
145
148
  return [] if location.filename != filename
146
- closure = locate_named_path_pin(location.range.start.line, location.range.start.character)
149
+ closure = locate_closure_pin(location.range.start.line, location.range.start.character)
147
150
  locals.select { |pin| pin.visible_at?(closure, location) }
148
151
  end
149
152
 
@@ -178,6 +181,7 @@ module Solargraph
178
181
 
179
182
  # @return [Hash{Class<Pin::Base> => Array<Pin::Base>}]
180
183
  def pin_class_hash
184
+ # @todo Need to support generic resolution in classify and transform_values
181
185
  @pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
182
186
  end
183
187
 
@@ -191,10 +195,12 @@ module Solargraph
191
195
  @convention_pins || []
192
196
  end
193
197
 
198
+ # @generic T
194
199
  # @param line [Integer]
195
200
  # @param character [Integer]
196
- # @param klasses [Array<Class>]
197
- # @return [Pin::Base, nil]
201
+ # @param klasses [Array<Class<generic<T>>>]
202
+ # @return [generic<T>, nil]
203
+ # @sg-ignore Need better generic inference here
198
204
  def _locate_pin line, character, *klasses
199
205
  position = Position.new(line, character)
200
206
  found = nil
@@ -202,7 +208,9 @@ module Solargraph
202
208
  # @todo Attribute pins should not be treated like closures, but
203
209
  # there's probably a better way to handle it
204
210
  next if pin.is_a?(Pin::Method) && pin.attribute?
211
+ # @sg-ignore Need to add nil check here
205
212
  found = pin if (klasses.empty? || klasses.any? { |kls| pin.is_a?(kls) } ) && pin.location.range.contain?(position)
213
+ # @sg-ignore Need to add nil check here
206
214
  break if pin.location.range.start.line > line
207
215
  end
208
216
  # Assuming the root pin is always valid
@@ -5,19 +5,21 @@ module Solargraph
5
5
  # A problem reported by TypeChecker.
6
6
  #
7
7
  class Problem
8
+ # @todo Missed nil violation
8
9
  # @return [Solargraph::Location]
9
10
  attr_reader :location
10
11
 
11
12
  # @return [String]
12
13
  attr_reader :message
13
14
 
15
+ # @todo Missed nil violation
14
16
  # @return [Pin::Base]
15
17
  attr_reader :pin
16
18
 
17
19
  # @return [String, nil]
18
20
  attr_reader :suggestion
19
21
 
20
- # @param location [Solargraph::Location]
22
+ # @param location [Solargraph::Location, nil]
21
23
  # @param message [String]
22
24
  # @param pin [Solargraph::Pin::Base, nil]
23
25
  # @param suggestion [String, nil]