solargraph 0.58.1 → 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 (162) 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/.rubocop_todo.yml +27 -49
  8. data/README.md +3 -3
  9. data/Rakefile +1 -0
  10. data/lib/solargraph/api_map/cache.rb +110 -110
  11. data/lib/solargraph/api_map/constants.rb +289 -279
  12. data/lib/solargraph/api_map/index.rb +204 -193
  13. data/lib/solargraph/api_map/source_to_yard.rb +109 -97
  14. data/lib/solargraph/api_map/store.rb +387 -384
  15. data/lib/solargraph/api_map.rb +1000 -945
  16. data/lib/solargraph/complex_type/conformance.rb +176 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +242 -228
  18. data/lib/solargraph/complex_type/unique_type.rb +632 -482
  19. data/lib/solargraph/complex_type.rb +549 -444
  20. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  21. data/lib/solargraph/convention/data_definition.rb +108 -105
  22. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  23. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  24. data/lib/solargraph/convention/struct_definition.rb +168 -164
  25. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  26. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  27. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  28. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  29. data/lib/solargraph/doc_map.rb +200 -439
  30. data/lib/solargraph/equality.rb +34 -34
  31. data/lib/solargraph/gem_pins.rb +97 -98
  32. data/lib/solargraph/language_server/host/dispatch.rb +131 -130
  33. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  34. data/lib/solargraph/language_server/host/sources.rb +100 -99
  35. data/lib/solargraph/language_server/host.rb +883 -878
  36. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
  37. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  38. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  39. data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
  40. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
  41. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  42. data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
  43. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  44. data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
  46. data/lib/solargraph/library.rb +729 -683
  47. data/lib/solargraph/location.rb +87 -82
  48. data/lib/solargraph/logging.rb +57 -37
  49. data/lib/solargraph/parser/comment_ripper.rb +76 -69
  50. data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
  51. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  52. data/lib/solargraph/parser/node_processor.rb +63 -62
  53. data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
  54. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  55. data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
  56. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  57. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  58. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  59. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  60. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  61. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  62. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
  63. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  64. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  65. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  66. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  68. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  69. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
  70. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
  71. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  72. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  73. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  74. data/lib/solargraph/parser/region.rb +75 -69
  75. data/lib/solargraph/parser/snippet.rb +17 -17
  76. data/lib/solargraph/pin/base.rb +761 -729
  77. data/lib/solargraph/pin/base_variable.rb +418 -126
  78. data/lib/solargraph/pin/block.rb +126 -104
  79. data/lib/solargraph/pin/breakable.rb +13 -9
  80. data/lib/solargraph/pin/callable.rb +278 -231
  81. data/lib/solargraph/pin/closure.rb +68 -72
  82. data/lib/solargraph/pin/common.rb +94 -79
  83. data/lib/solargraph/pin/compound_statement.rb +55 -0
  84. data/lib/solargraph/pin/conversions.rb +124 -123
  85. data/lib/solargraph/pin/delegated_method.rb +131 -120
  86. data/lib/solargraph/pin/documenting.rb +115 -114
  87. data/lib/solargraph/pin/instance_variable.rb +38 -34
  88. data/lib/solargraph/pin/keyword.rb +16 -20
  89. data/lib/solargraph/pin/local_variable.rb +31 -75
  90. data/lib/solargraph/pin/method.rb +720 -672
  91. data/lib/solargraph/pin/method_alias.rb +42 -34
  92. data/lib/solargraph/pin/namespace.rb +121 -115
  93. data/lib/solargraph/pin/parameter.rb +338 -275
  94. data/lib/solargraph/pin/proxy_type.rb +40 -39
  95. data/lib/solargraph/pin/reference/override.rb +47 -47
  96. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  97. data/lib/solargraph/pin/reference.rb +41 -39
  98. data/lib/solargraph/pin/search.rb +62 -61
  99. data/lib/solargraph/pin/signature.rb +69 -61
  100. data/lib/solargraph/pin/symbol.rb +53 -53
  101. data/lib/solargraph/pin/until.rb +18 -18
  102. data/lib/solargraph/pin/while.rb +18 -18
  103. data/lib/solargraph/pin.rb +46 -44
  104. data/lib/solargraph/pin_cache.rb +665 -245
  105. data/lib/solargraph/position.rb +118 -119
  106. data/lib/solargraph/range.rb +112 -112
  107. data/lib/solargraph/rbs_map/conversions.rb +846 -823
  108. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  109. data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
  110. data/lib/solargraph/rbs_map.rb +217 -163
  111. data/lib/solargraph/shell.rb +397 -352
  112. data/lib/solargraph/source/chain/call.rb +372 -337
  113. data/lib/solargraph/source/chain/constant.rb +28 -26
  114. data/lib/solargraph/source/chain/hash.rb +35 -34
  115. data/lib/solargraph/source/chain/if.rb +29 -28
  116. data/lib/solargraph/source/chain/instance_variable.rb +34 -13
  117. data/lib/solargraph/source/chain/literal.rb +53 -48
  118. data/lib/solargraph/source/chain/or.rb +31 -23
  119. data/lib/solargraph/source/chain.rb +294 -291
  120. data/lib/solargraph/source/change.rb +89 -82
  121. data/lib/solargraph/source/cursor.rb +172 -166
  122. data/lib/solargraph/source/source_chainer.rb +204 -194
  123. data/lib/solargraph/source/updater.rb +59 -55
  124. data/lib/solargraph/source.rb +524 -498
  125. data/lib/solargraph/source_map/clip.rb +237 -226
  126. data/lib/solargraph/source_map/data.rb +37 -34
  127. data/lib/solargraph/source_map/mapper.rb +282 -259
  128. data/lib/solargraph/source_map.rb +220 -212
  129. data/lib/solargraph/type_checker/problem.rb +34 -32
  130. data/lib/solargraph/type_checker/rules.rb +157 -84
  131. data/lib/solargraph/type_checker.rb +895 -814
  132. data/lib/solargraph/version.rb +1 -1
  133. data/lib/solargraph/workspace/config.rb +257 -255
  134. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  135. data/lib/solargraph/workspace/require_paths.rb +98 -97
  136. data/lib/solargraph/workspace.rb +362 -220
  137. data/lib/solargraph/yard_map/helpers.rb +45 -44
  138. data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
  139. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  140. data/lib/solargraph/yard_map/mapper.rb +84 -79
  141. data/lib/solargraph/yardoc.rb +97 -87
  142. data/lib/solargraph.rb +126 -105
  143. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  144. data/rbs/fills/tuple/tuple.rbs +28 -0
  145. data/rbs/shims/ast/0/node.rbs +5 -0
  146. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  147. data/rbs_collection.yaml +1 -1
  148. data/solargraph.gemspec +2 -1
  149. metadata +22 -17
  150. data/lib/solargraph/type_checker/checks.rb +0 -124
  151. data/lib/solargraph/type_checker/param_def.rb +0 -37
  152. data/lib/solargraph/yard_map/to_method.rb +0 -89
  153. data/sig/shims/ast/0/node.rbs +0 -5
  154. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  155. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  156. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  157. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  158. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  159. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  160. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  161. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  162. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,194 +1,204 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- # Information about a location in a source, including the location's word
6
- # and signature, literal values at the base of signatures, and whether the
7
- # location is inside a string or comment. ApiMaps use Fragments to provide
8
- # results for completion and definition queries.
9
- #
10
- class SourceChainer
11
- # include Source::NodeMethods
12
-
13
- private_class_method :new
14
-
15
- class << self
16
- # @param source [Source]
17
- # @param position [Position, Array(Integer, Integer)]
18
- # @return [Source::Chain]
19
- def chain source, position
20
- new(source, Solargraph::Position.normalize(position)).chain
21
- end
22
- end
23
-
24
- # @param source [Source]
25
- # @param position [Position]
26
- def initialize source, position
27
- @source = source
28
- @position = position
29
- @calculated_literal = false
30
- end
31
-
32
- # @return [Source::Chain]
33
- def chain
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)
38
- begin
39
- return Chain.new([]) if phrase.end_with?('..')
40
- node = nil
41
- parent = nil
42
- if !source.repaired? && source.parsed? && source.synchronized?
43
- tree = source.tree_at(position.line, position.column)
44
- node, parent = tree[0..2]
45
- elsif source.parsed? && source.repaired? && end_of_phrase == '.'
46
- node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
47
- node = Parser.parse(fixed_phrase) if node.nil?
48
- elsif source.repaired?
49
- node = Parser.parse(fixed_phrase)
50
- 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)}
52
- # Exception for positions that chain literal nodes in unsynchronized sources
53
- node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
54
- node = Parser.parse(fixed_phrase) if node.nil?
55
- end
56
- rescue Parser::SyntaxError
57
- return Chain.new([Chain::UNDEFINED_CALL])
58
- end
59
- return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
60
- # chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
61
- chain = Parser.chain(node, source.filename, parent)
62
- if source.repaired? || !source.parsed? || !source.synchronized?
63
- if end_of_phrase.strip == '.'
64
- chain.links.push Chain::UNDEFINED_CALL
65
- elsif end_of_phrase.strip == '::'
66
- chain.links.push Chain::UNDEFINED_CONSTANT
67
- end
68
- elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::'
69
- chain.links.push Source::Chain::UNDEFINED_CONSTANT
70
- end
71
- chain
72
- end
73
-
74
- private
75
-
76
- # @return [Position]
77
- attr_reader :position
78
-
79
- # @return [Solargraph::Source]
80
- attr_reader :source
81
-
82
- # @return [String]
83
- def phrase
84
- @phrase ||= source.code[signature_data..offset-1]
85
- end
86
-
87
- # @return [String]
88
- def fixed_phrase
89
- @fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
90
- end
91
-
92
- # @return [Position]
93
- def fixed_position
94
- @fixed_position ||= Position.from_offset(source.code, offset - end_of_phrase.length)
95
- end
96
-
97
- # @return [String]
98
- def end_of_phrase
99
- @end_of_phrase ||= begin
100
- match = phrase.match(/\s*(\.{1}|::)\s*$/)
101
- if match
102
- match[0]
103
- else
104
- ''
105
- end
106
- end
107
- end
108
-
109
- # True if the current offset is inside a string.
110
- #
111
- # @return [Boolean]
112
- def string?
113
- # @string ||= (node.type == :str or node.type == :dstr)
114
- @string ||= @source.string_at?(position)
115
- end
116
-
117
- # @return [Integer]
118
- def offset
119
- @offset ||= get_offset(position.line, position.column)
120
- end
121
-
122
- # @param line [Integer]
123
- # @param column [Integer]
124
- # @return [Integer]
125
- def get_offset line, column
126
- Position.line_char_to_offset(@source.code, line, column)
127
- end
128
-
129
- # @return [Integer]
130
- def signature_data
131
- @signature_data ||= get_signature_data_at(offset)
132
- end
133
-
134
- # @param index [Integer]
135
- # @return [Integer]
136
- def get_signature_data_at index
137
- brackets = 0
138
- squares = 0
139
- parens = 0
140
- index -=1
141
- in_whitespace = false
142
- while index >= 0
143
- 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
146
- char = @source.code[index, 1]
147
- 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)
149
- in_whitespace = true
150
- 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
158
- end
159
- if char == ')'
160
- parens -=1
161
- elsif char == ']'
162
- squares -=1
163
- elsif char == '}'
164
- brackets -= 1
165
- elsif char == '('
166
- parens += 1
167
- elsif char == '{'
168
- brackets += 1
169
- elsif char == '['
170
- squares += 1
171
- end
172
- if brackets.zero? and parens.zero? and squares.zero?
173
- break if ['"', "'", ',', ';', '%'].include?(char)
174
- break if ['!', '?'].include?(char) && index < offset - 1
175
- break if char == '$'
176
- if char == '@'
177
- index -= 1
178
- if @source.code[index, 1] == '@'
179
- index -= 1
180
- end
181
- break
182
- end
183
- elsif parens == 1 || brackets == 1 || squares == 1
184
- break
185
- end
186
- in_whitespace = false
187
- end
188
- index -= 1
189
- end
190
- index + 1
191
- end
192
- end
193
- end
194
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ # Information about a location in a source, including the location's word
6
+ # and signature, literal values at the base of signatures, and whether the
7
+ # location is inside a string or comment. ApiMaps use Fragments to provide
8
+ # results for completion and definition queries.
9
+ #
10
+ class SourceChainer
11
+ # include Source::NodeMethods
12
+
13
+ private_class_method :new
14
+
15
+ class << self
16
+ # @param source [Source]
17
+ # @param position [Position, Array(Integer, Integer)]
18
+ # @return [Source::Chain]
19
+ def chain source, position
20
+ new(source, Solargraph::Position.normalize(position)).chain
21
+ end
22
+ end
23
+
24
+ # @param source [Source]
25
+ # @param position [Position]
26
+ def initialize source, position
27
+ @source = source
28
+ @position = position
29
+ @calculated_literal = false
30
+ end
31
+
32
+ # @return [Source::Chain]
33
+ def chain
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
+ # @sg-ignore Need to add nil check here
37
+ return Chain.new([Chain::Literal.new('Symbol', phrase[1..].to_sym)]) if phrase.start_with?(':') && !phrase.start_with?('::')
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)
39
+ begin
40
+ return Chain.new([]) if phrase.end_with?('..')
41
+ # @type [::Parser::AST::Node, nil]
42
+ node = nil
43
+ # @type [::Parser::AST::Node, nil]
44
+ parent = nil
45
+ if !source.repaired? && source.parsed? && source.synchronized?
46
+ tree = source.tree_at(position.line, position.column)
47
+ node, parent = tree[0..2]
48
+ elsif source.parsed? && source.repaired? && end_of_phrase == '.'
49
+ node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
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?
52
+ elsif source.repaired?
53
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
54
+ else
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)}
56
+ # Exception for positions that chain literal nodes in unsynchronized sources
57
+ node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
58
+ node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
59
+ end
60
+ rescue Parser::SyntaxError
61
+ return Chain.new([Chain::UNDEFINED_CALL])
62
+ end
63
+ return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
64
+ # chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
65
+ chain = Parser.chain(node, source.filename, parent)
66
+ if source.repaired? || !source.parsed? || !source.synchronized?
67
+ if end_of_phrase.strip == '.'
68
+ chain.links.push Chain::UNDEFINED_CALL
69
+ elsif end_of_phrase.strip == '::'
70
+ chain.links.push Chain::UNDEFINED_CONSTANT
71
+ end
72
+ elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::'
73
+ chain.links.push Source::Chain::UNDEFINED_CONSTANT
74
+ end
75
+ chain
76
+ end
77
+
78
+ private
79
+
80
+ # @return [Position]
81
+ attr_reader :position
82
+
83
+ # @return [Solargraph::Source]
84
+ attr_reader :source
85
+
86
+ # @sg-ignore Need to add nil check here
87
+ # @return [String]
88
+ def phrase
89
+ @phrase ||= source.code[signature_data..offset-1]
90
+ end
91
+
92
+ # @sg-ignore Need to add nil check here
93
+ # @return [String]
94
+ def fixed_phrase
95
+ @fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
96
+ end
97
+
98
+ # @return [Position]
99
+ def fixed_position
100
+ @fixed_position ||= Position.from_offset(source.code, offset - end_of_phrase.length)
101
+ end
102
+
103
+ # @return [String]
104
+ # @sg-ignore Need to add nil check here
105
+ def end_of_phrase
106
+ @end_of_phrase ||= begin
107
+ match = phrase.match(/\s*(\.{1}|::)\s*$/)
108
+ if match
109
+ match[0]
110
+ else
111
+ ''
112
+ end
113
+ end
114
+ end
115
+
116
+ # True if the current offset is inside a string.
117
+ #
118
+ # @return [Boolean]
119
+ def string?
120
+ # @string ||= (node.type == :str or node.type == :dstr)
121
+ @string ||= @source.string_at?(position)
122
+ end
123
+
124
+ # @return [Integer]
125
+ def offset
126
+ @offset ||= get_offset(position.line, position.column)
127
+ end
128
+
129
+ # @param line [Integer]
130
+ # @param column [Integer]
131
+ # @return [Integer]
132
+ def get_offset line, column
133
+ Position.line_char_to_offset(@source.code, line, column)
134
+ end
135
+
136
+ # @return [Integer]
137
+ def signature_data
138
+ @signature_data ||= get_signature_data_at(offset)
139
+ end
140
+
141
+ # @param index [Integer]
142
+ # @return [Integer]
143
+ def get_signature_data_at index
144
+ brackets = 0
145
+ squares = 0
146
+ parens = 0
147
+ index -=1
148
+ in_whitespace = false
149
+ while index >= 0
150
+ pos = Position.from_offset(@source.code, index)
151
+ break if index > 0 and @source.comment_at?(pos)
152
+ break if brackets > 0 or parens > 0 or squares > 0
153
+ char = @source.code[index, 1]
154
+ break if char.nil? # @todo Is this the right way to handle this?
155
+ if brackets.zero? and parens.zero? and squares.zero? and [' ', "\r", "\n", "\t"].include?(char)
156
+ in_whitespace = true
157
+ else
158
+ if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
159
+ # @sg-ignore Need to add nil check here
160
+ unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
161
+ old = @source.code[index+1..-1]
162
+ # @sg-ignore Need to add nil check here
163
+ nxt = @source.code[index+1..-1].lstrip
164
+ # @sg-ignore Need to add nil check here
165
+ index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
166
+ break
167
+ end
168
+ end
169
+ if char == ')'
170
+ parens -=1
171
+ elsif char == ']'
172
+ squares -=1
173
+ elsif char == '}'
174
+ brackets -= 1
175
+ elsif char == '('
176
+ parens += 1
177
+ elsif char == '{'
178
+ brackets += 1
179
+ elsif char == '['
180
+ squares += 1
181
+ end
182
+ if brackets.zero? and parens.zero? and squares.zero?
183
+ break if ['"', "'", ',', ';', '%'].include?(char)
184
+ break if ['!', '?'].include?(char) && index < offset - 1
185
+ break if char == '$'
186
+ if char == '@'
187
+ index -= 1
188
+ if @source.code[index, 1] == '@'
189
+ index -= 1
190
+ end
191
+ break
192
+ end
193
+ elsif parens == 1 || brackets == 1 || squares == 1
194
+ break
195
+ end
196
+ in_whitespace = false
197
+ end
198
+ index -= 1
199
+ end
200
+ index + 1
201
+ end
202
+ end
203
+ end
204
+ end
@@ -1,55 +1,59 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- class Source
5
- # Updaters contain changes to be applied to a source. The source applies
6
- # the update via the Source#synchronize method.
7
- #
8
- class Updater
9
- # @return [String]
10
- attr_reader :filename
11
-
12
- # @return [Integer]
13
- attr_reader :version
14
-
15
- # @return [Array<Change>]
16
- attr_reader :changes
17
-
18
- # @param filename [String] The file to update.
19
- # @param version [Integer] A version number associated with this update.
20
- # @param changes [Array<Solargraph::Source::Change>] The changes.
21
- def initialize filename, version, changes
22
- @filename = filename
23
- @version = version
24
- @changes = changes
25
- @input = nil
26
- @did_nullify = nil
27
- @output = nil
28
- end
29
-
30
- # @param text [String]
31
- # @param nullable [Boolean]
32
- # @return [String]
33
- def write text, nullable = false
34
- can_nullify = (nullable and changes.length == 1)
35
- return @output if @input == text and can_nullify == @did_nullify
36
- @input = text
37
- @output = text
38
- @did_nullify = can_nullify
39
- changes.each do |ch|
40
- @output = ch.write(@output, can_nullify)
41
- end
42
- @output
43
- end
44
-
45
- # @param text [String]
46
- # @return [String]
47
- def repair text
48
- changes.each do |ch|
49
- text = ch.repair(text)
50
- end
51
- text
52
- end
53
- end
54
- end
55
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ # Updaters contain changes to be applied to a source. The source applies
6
+ # the update via the Source#synchronize method.
7
+ #
8
+ class Updater
9
+ # @return [String]
10
+ attr_reader :filename
11
+
12
+ # @return [Integer]
13
+ attr_reader :version
14
+
15
+ # @return [Array<Change>]
16
+ attr_reader :changes
17
+
18
+ # @param filename [String] The file to update.
19
+ # @param version [Integer] A version number associated with this update.
20
+ # @param changes [Array<Solargraph::Source::Change>] The changes.
21
+ def initialize filename, version, changes
22
+ @filename = filename
23
+ @version = version
24
+ @changes = changes
25
+ @input = nil
26
+ @did_nullify = nil
27
+ @output = nil
28
+ end
29
+
30
+ # @param text [String]
31
+ # @param nullable [Boolean]
32
+ # @sg-ignore changes doesn't mutate @output, so this can never be nil
33
+ # @return [String]
34
+ def write text, nullable = false
35
+ can_nullify = (nullable and changes.length == 1)
36
+ return @output if @input == text and can_nullify == @did_nullify
37
+ @input = text
38
+ @output = text
39
+ @did_nullify = can_nullify
40
+ changes.each do |ch|
41
+ # @sg-ignore Wrong argument type for
42
+ # Solargraph::Source::Change#write: text expected String,
43
+ # received String, nil
44
+ @output = ch.write(@output, can_nullify)
45
+ end
46
+ @output
47
+ end
48
+
49
+ # @param text [String]
50
+ # @return [String]
51
+ def repair text
52
+ changes.each do |ch|
53
+ text = ch.repair(text)
54
+ end
55
+ text
56
+ end
57
+ end
58
+ end
59
+ end