solargraph 0.32.1 → 0.32.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +25 -0
  6. data/EXAMPLES.md +76 -0
  7. data/Gemfile +3 -0
  8. data/LANGUAGE_SERVER.md +51 -0
  9. data/LICENSE +21 -0
  10. data/OVERVIEW.md +37 -0
  11. data/README.md +106 -0
  12. data/Rakefile +14 -0
  13. data/SERVER.md +95 -0
  14. data/bin/solargraph +0 -0
  15. data/bin/solargraph-runtime +5 -5
  16. data/lib/solargraph.rb +54 -54
  17. data/lib/solargraph/api_map.rb +659 -659
  18. data/lib/solargraph/api_map/cache.rb +49 -49
  19. data/lib/solargraph/api_map/source_to_yard.rb +67 -67
  20. data/lib/solargraph/api_map/store.rb +201 -201
  21. data/lib/solargraph/bundle.rb +24 -24
  22. data/lib/solargraph/complex_type.rb +150 -150
  23. data/lib/solargraph/complex_type/type_methods.rb +124 -124
  24. data/lib/solargraph/complex_type/unique_type.rb +44 -44
  25. data/lib/solargraph/core_fills.rb +37 -37
  26. data/lib/solargraph/diagnostics.rb +52 -52
  27. data/lib/solargraph/diagnostics/base.rb +20 -20
  28. data/lib/solargraph/diagnostics/require_not_found.rb +28 -28
  29. data/lib/solargraph/diagnostics/rubocop.rb +98 -98
  30. data/lib/solargraph/diagnostics/rubocop_helpers.rb +46 -46
  31. data/lib/solargraph/diagnostics/type_not_defined.rb +108 -108
  32. data/lib/solargraph/diagnostics/update_errors.rb +38 -38
  33. data/lib/solargraph/language_server/completion_item_kinds.rb +33 -33
  34. data/lib/solargraph/language_server/error_codes.rb +18 -18
  35. data/lib/solargraph/language_server/host.rb +684 -681
  36. data/lib/solargraph/language_server/host/cataloger.rb +54 -79
  37. data/lib/solargraph/language_server/host/diagnoser.rb +80 -80
  38. data/lib/solargraph/language_server/host/dispatch.rb +112 -113
  39. data/lib/solargraph/language_server/host/sources.rb +138 -138
  40. data/lib/solargraph/language_server/message.rb +90 -90
  41. data/lib/solargraph/language_server/message/base.rb +83 -83
  42. data/lib/solargraph/language_server/message/completion_item/resolve.rb +40 -40
  43. data/lib/solargraph/language_server/message/exit_notification.rb +11 -11
  44. data/lib/solargraph/language_server/message/extended.rb +19 -19
  45. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +86 -86
  46. data/lib/solargraph/language_server/message/extended/document.rb +18 -18
  47. data/lib/solargraph/language_server/message/extended/document_gems.rb +30 -30
  48. data/lib/solargraph/language_server/message/extended/environment.rb +20 -20
  49. data/lib/solargraph/language_server/message/extended/search.rb +18 -18
  50. data/lib/solargraph/language_server/message/initialize.rb +141 -141
  51. data/lib/solargraph/language_server/message/initialized.rb +23 -23
  52. data/lib/solargraph/language_server/message/shutdown.rb +11 -11
  53. data/lib/solargraph/language_server/message/text_document.rb +25 -25
  54. data/lib/solargraph/language_server/message/text_document/completion.rb +51 -51
  55. data/lib/solargraph/language_server/message/text_document/definition.rb +18 -18
  56. data/lib/solargraph/language_server/message/text_document/did_change.rb +13 -13
  57. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +21 -21
  58. data/lib/solargraph/language_server/message/text_document/folding_range.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/formatting.rb +50 -50
  60. data/lib/solargraph/language_server/message/text_document/hover.rb +31 -31
  61. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +32 -32
  62. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +9 -9
  63. data/lib/solargraph/language_server/message/text_document/references.rb +14 -14
  64. data/lib/solargraph/language_server/message/text_document/rename.rb +17 -17
  65. data/lib/solargraph/language_server/message/text_document/signature_help.rb +19 -19
  66. data/lib/solargraph/language_server/message/workspace.rb +12 -12
  67. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -29
  68. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +29 -27
  69. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  70. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +21 -21
  71. data/lib/solargraph/language_server/request.rb +22 -22
  72. data/lib/solargraph/language_server/symbol_kinds.rb +34 -34
  73. data/lib/solargraph/language_server/transport.rb +11 -11
  74. data/lib/solargraph/language_server/transport/adapter.rb +60 -60
  75. data/lib/solargraph/language_server/transport/data_reader.rb +66 -66
  76. data/lib/solargraph/language_server/uri_helpers.rb +25 -25
  77. data/lib/solargraph/library.rb +421 -419
  78. data/lib/solargraph/live_map.rb +126 -126
  79. data/lib/solargraph/live_map/cache.rb +38 -38
  80. data/lib/solargraph/location.rb +31 -31
  81. data/lib/solargraph/logging.rb +25 -25
  82. data/lib/solargraph/page.rb +68 -68
  83. data/lib/solargraph/pin.rb +50 -50
  84. data/lib/solargraph/pin/attribute.rb +41 -41
  85. data/lib/solargraph/pin/base.rb +280 -280
  86. data/lib/solargraph/pin/base_method.rb +76 -76
  87. data/lib/solargraph/pin/base_variable.rb +72 -72
  88. data/lib/solargraph/pin/block.rb +32 -32
  89. data/lib/solargraph/pin/block_parameter.rb +103 -103
  90. data/lib/solargraph/pin/class_variable.rb +9 -9
  91. data/lib/solargraph/pin/constant.rb +30 -30
  92. data/lib/solargraph/pin/conversions.rb +79 -79
  93. data/lib/solargraph/pin/documenting.rb +41 -41
  94. data/lib/solargraph/pin/duck_method.rb +14 -14
  95. data/lib/solargraph/pin/global_variable.rb +9 -9
  96. data/lib/solargraph/pin/instance_variable.rb +9 -9
  97. data/lib/solargraph/pin/keyword.rb +17 -17
  98. data/lib/solargraph/pin/local_variable.rb +23 -23
  99. data/lib/solargraph/pin/localized.rb +22 -22
  100. data/lib/solargraph/pin/method.rb +126 -126
  101. data/lib/solargraph/pin/method_alias.rb +30 -30
  102. data/lib/solargraph/pin/method_parameter.rb +40 -40
  103. data/lib/solargraph/pin/namespace.rb +54 -54
  104. data/lib/solargraph/pin/plugin/method.rb +25 -25
  105. data/lib/solargraph/pin/proxy_type.rb +35 -35
  106. data/lib/solargraph/pin/reference.rb +22 -22
  107. data/lib/solargraph/pin/reference/extend.rb +11 -11
  108. data/lib/solargraph/pin/reference/include.rb +11 -11
  109. data/lib/solargraph/pin/reference/require.rb +15 -15
  110. data/lib/solargraph/pin/reference/superclass.rb +11 -11
  111. data/lib/solargraph/pin/symbol.rb +44 -44
  112. data/lib/solargraph/pin/yard_pin.rb +10 -10
  113. data/lib/solargraph/pin/yard_pin/constant.rb +14 -14
  114. data/lib/solargraph/pin/yard_pin/method.rb +35 -35
  115. data/lib/solargraph/pin/yard_pin/namespace.rb +19 -19
  116. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +14 -14
  117. data/lib/solargraph/plugin.rb +8 -8
  118. data/lib/solargraph/plugin/base.rb +41 -41
  119. data/lib/solargraph/plugin/canceler.rb +11 -11
  120. data/lib/solargraph/plugin/process.rb +172 -172
  121. data/lib/solargraph/plugin/runtime.rb +134 -134
  122. data/lib/solargraph/position.rb +110 -110
  123. data/lib/solargraph/range.rb +83 -83
  124. data/lib/solargraph/server_methods.rb +14 -14
  125. data/lib/solargraph/shell.rb +102 -102
  126. data/lib/solargraph/source.rb +521 -521
  127. data/lib/solargraph/source/chain.rb +120 -120
  128. data/lib/solargraph/source/chain/call.rb +107 -107
  129. data/lib/solargraph/source/chain/class_variable.rb +11 -11
  130. data/lib/solargraph/source/chain/constant.rb +30 -30
  131. data/lib/solargraph/source/chain/global_variable.rb +11 -11
  132. data/lib/solargraph/source/chain/head.rb +33 -33
  133. data/lib/solargraph/source/chain/instance_variable.rb +11 -11
  134. data/lib/solargraph/source/chain/link.rb +33 -33
  135. data/lib/solargraph/source/chain/literal.rb +21 -21
  136. data/lib/solargraph/source/chain/variable.rb +11 -11
  137. data/lib/solargraph/source/change.rb +77 -77
  138. data/lib/solargraph/source/cursor.rb +157 -157
  139. data/lib/solargraph/source/node_chainer.rb +96 -96
  140. data/lib/solargraph/source/node_methods.rb +225 -225
  141. data/lib/solargraph/source/source_chainer.rb +183 -183
  142. data/lib/solargraph/source_map.rb +169 -169
  143. data/lib/solargraph/source_map/clip.rb +145 -145
  144. data/lib/solargraph/source_map/completion.rb +21 -21
  145. data/lib/solargraph/source_map/mapper.rb +149 -149
  146. data/lib/solargraph/source_map/node_processor.rb +78 -78
  147. data/lib/solargraph/source_map/node_processor/alias_node.rb +19 -19
  148. data/lib/solargraph/source_map/node_processor/args_node.rb +28 -28
  149. data/lib/solargraph/source_map/node_processor/base.rb +68 -68
  150. data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -11
  151. data/lib/solargraph/source_map/node_processor/block_node.rb +14 -14
  152. data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -14
  153. data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -14
  154. data/lib/solargraph/source_map/node_processor/def_node.rb +54 -54
  155. data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -21
  156. data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -12
  157. data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -18
  158. data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -16
  159. data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -26
  160. data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -12
  161. data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -11
  162. data/lib/solargraph/source_map/node_processor/send_node.rb +162 -162
  163. data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -11
  164. data/lib/solargraph/source_map/region.rb +58 -58
  165. data/lib/solargraph/version.rb +3 -3
  166. data/lib/solargraph/views/environment.erb +53 -53
  167. data/lib/solargraph/workspace.rb +183 -183
  168. data/lib/solargraph/workspace/config.rb +170 -170
  169. data/lib/solargraph/yard_map.rb +298 -298
  170. data/lib/solargraph/yard_map/cache.rb +17 -17
  171. data/lib/solargraph/yard_map/core_docs.rb +163 -163
  172. data/lib/solargraph/yard_map/core_gen.rb +76 -76
  173. data/lib/yard-coregen.rb +16 -16
  174. data/lib/yard-solargraph.rb +18 -18
  175. data/solargraph.gemspec +37 -0
  176. data/travis-bundler.rb +10 -0
  177. metadata +19 -6
@@ -1,157 +1,157 @@
1
- module Solargraph
2
- class Source
3
- # Information about a position in a source, including the word located
4
- # there.
5
- #
6
- class Cursor
7
- # @return [Position]
8
- attr_reader :position
9
-
10
- # @return [Source]
11
- attr_reader :source
12
-
13
- # @param source [Source]
14
- # @param position [Position, Array(Integer, Integer)]
15
- def initialize source, position
16
- @source = source
17
- @position = Position.normalize(position)
18
- end
19
-
20
- # @return [String]
21
- def filename
22
- source.filename
23
- end
24
-
25
- # The whole word at the current position. Given the text `foo.bar`, the
26
- # word at position(0,6) is `bar`.
27
- #
28
- # @return [String]
29
- def word
30
- @word ||= start_of_word + end_of_word
31
- end
32
-
33
- # The part of the word before the current position. Given the text
34
- # `foo.bar`, the start_of_word at position(0, 6) is `ba`.
35
- #
36
- # @return [String]
37
- def start_of_word
38
- @start_of_word ||= begin
39
- match = source.code[0..offset-1].to_s.match(start_word_pattern)
40
- result = (match ? match[0] : '')
41
- # Including the preceding colon if the word appears to be a symbol
42
- result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
43
- result
44
- end
45
- end
46
-
47
- # The part of the word after the current position. Given the text
48
- # `foo.bar`, the end_of_word at position (0,6) is `r`.
49
- #
50
- # @return [String]
51
- def end_of_word
52
- @end_of_word ||= begin
53
- match = source.code[offset..-1].to_s.match(end_word_pattern)
54
- match ? match[0] : ''
55
- end
56
- end
57
-
58
- def start_of_constant?
59
- source.code[offset-2, 2] == '::'
60
- end
61
-
62
- # The range of the word at the current position.
63
- #
64
- # @return [Range]
65
- def range
66
- @range ||= begin
67
- s = Position.from_offset(source.code, offset - start_of_word.length)
68
- e = Position.from_offset(source.code, offset + end_of_word.length)
69
- Solargraph::Range.new(s, e)
70
- end
71
- end
72
-
73
- # @return [Chain]
74
- def chain
75
- @chain ||= SourceChainer.chain(source, position)
76
- end
77
-
78
- # @return [Boolean]
79
- def argument?
80
- @argument ||= !signature_position.nil?
81
- end
82
-
83
- # @return [Boolean]
84
- def comment?
85
- @comment ||= source.comment_at?(position)
86
- end
87
-
88
- # @return [Boolean]
89
- def string?
90
- @string ||= source.string_at?(position)
91
- end
92
-
93
- # @return [Cursor, nil]
94
- def recipient
95
- return nil unless argument?
96
- @recipient ||= Cursor.new(source, signature_position)
97
- end
98
-
99
- def node_position
100
- @node_position ||= begin
101
- if start_of_word.empty?
102
- match = source.code[0, offset].match(/[\s]*(\.|:+)[\s]*$/)
103
- if match
104
- Position.from_offset(source.code, offset - match[0].length)
105
- else
106
- position
107
- end
108
- else
109
- position
110
- end
111
- end
112
- end
113
-
114
- private
115
-
116
- # @return [Integer]
117
- def offset
118
- @offset ||= Position.to_offset(source.code, position)
119
- end
120
-
121
- # A regular expression to find the start of a word from an offset.
122
- #
123
- # @return [Regexp]
124
- def start_word_pattern
125
- /(@{1,2}|\$)?([a-z0-9_]|[^\u0000-\u007F])*\z/i
126
- end
127
-
128
- # A regular expression to find the end of a word from an offset.
129
- #
130
- # @return [Regexp]
131
- def end_word_pattern
132
- /^([a-z0-9_]|[^\u0000-\u007F])*[\?\!]?/i
133
- end
134
-
135
- def signature_position
136
- if @signature_position.nil?
137
- open_parens = 0
138
- cursor = offset - 1
139
- while cursor >= 0
140
- break if cursor < 0
141
- if source.code[cursor] == ')'
142
- open_parens -= 1
143
- elsif source.code[cursor] == '('
144
- open_parens += 1
145
- end
146
- break if open_parens == 1
147
- cursor -= 1
148
- end
149
- if cursor >= 0
150
- @signature_position = Position.from_offset(source.code, cursor)
151
- end
152
- end
153
- @signature_position
154
- end
155
- end
156
- end
157
- end
1
+ module Solargraph
2
+ class Source
3
+ # Information about a position in a source, including the word located
4
+ # there.
5
+ #
6
+ class Cursor
7
+ # @return [Position]
8
+ attr_reader :position
9
+
10
+ # @return [Source]
11
+ attr_reader :source
12
+
13
+ # @param source [Source]
14
+ # @param position [Position, Array(Integer, Integer)]
15
+ def initialize source, position
16
+ @source = source
17
+ @position = Position.normalize(position)
18
+ end
19
+
20
+ # @return [String]
21
+ def filename
22
+ source.filename
23
+ end
24
+
25
+ # The whole word at the current position. Given the text `foo.bar`, the
26
+ # word at position(0,6) is `bar`.
27
+ #
28
+ # @return [String]
29
+ def word
30
+ @word ||= start_of_word + end_of_word
31
+ end
32
+
33
+ # The part of the word before the current position. Given the text
34
+ # `foo.bar`, the start_of_word at position(0, 6) is `ba`.
35
+ #
36
+ # @return [String]
37
+ def start_of_word
38
+ @start_of_word ||= begin
39
+ match = source.code[0..offset-1].to_s.match(start_word_pattern)
40
+ result = (match ? match[0] : '')
41
+ # Including the preceding colon if the word appears to be a symbol
42
+ result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
43
+ result
44
+ end
45
+ end
46
+
47
+ # The part of the word after the current position. Given the text
48
+ # `foo.bar`, the end_of_word at position (0,6) is `r`.
49
+ #
50
+ # @return [String]
51
+ def end_of_word
52
+ @end_of_word ||= begin
53
+ match = source.code[offset..-1].to_s.match(end_word_pattern)
54
+ match ? match[0] : ''
55
+ end
56
+ end
57
+
58
+ def start_of_constant?
59
+ source.code[offset-2, 2] == '::'
60
+ end
61
+
62
+ # The range of the word at the current position.
63
+ #
64
+ # @return [Range]
65
+ def range
66
+ @range ||= begin
67
+ s = Position.from_offset(source.code, offset - start_of_word.length)
68
+ e = Position.from_offset(source.code, offset + end_of_word.length)
69
+ Solargraph::Range.new(s, e)
70
+ end
71
+ end
72
+
73
+ # @return [Chain]
74
+ def chain
75
+ @chain ||= SourceChainer.chain(source, position)
76
+ end
77
+
78
+ # @return [Boolean]
79
+ def argument?
80
+ @argument ||= !signature_position.nil?
81
+ end
82
+
83
+ # @return [Boolean]
84
+ def comment?
85
+ @comment ||= source.comment_at?(position)
86
+ end
87
+
88
+ # @return [Boolean]
89
+ def string?
90
+ @string ||= source.string_at?(position)
91
+ end
92
+
93
+ # @return [Cursor, nil]
94
+ def recipient
95
+ return nil unless argument?
96
+ @recipient ||= Cursor.new(source, signature_position)
97
+ end
98
+
99
+ def node_position
100
+ @node_position ||= begin
101
+ if start_of_word.empty?
102
+ match = source.code[0, offset].match(/[\s]*(\.|:+)[\s]*$/)
103
+ if match
104
+ Position.from_offset(source.code, offset - match[0].length)
105
+ else
106
+ position
107
+ end
108
+ else
109
+ position
110
+ end
111
+ end
112
+ end
113
+
114
+ private
115
+
116
+ # @return [Integer]
117
+ def offset
118
+ @offset ||= Position.to_offset(source.code, position)
119
+ end
120
+
121
+ # A regular expression to find the start of a word from an offset.
122
+ #
123
+ # @return [Regexp]
124
+ def start_word_pattern
125
+ /(@{1,2}|\$)?([a-z0-9_]|[^\u0000-\u007F])*\z/i
126
+ end
127
+
128
+ # A regular expression to find the end of a word from an offset.
129
+ #
130
+ # @return [Regexp]
131
+ def end_word_pattern
132
+ /^([a-z0-9_]|[^\u0000-\u007F])*[\?\!]?/i
133
+ end
134
+
135
+ def signature_position
136
+ if @signature_position.nil?
137
+ open_parens = 0
138
+ cursor = offset - 1
139
+ while cursor >= 0
140
+ break if cursor < 0
141
+ if source.code[cursor] == ')'
142
+ open_parens -= 1
143
+ elsif source.code[cursor] == '('
144
+ open_parens += 1
145
+ end
146
+ break if open_parens == 1
147
+ cursor -= 1
148
+ end
149
+ if cursor >= 0
150
+ @signature_position = Position.from_offset(source.code, cursor)
151
+ end
152
+ end
153
+ @signature_position
154
+ end
155
+ end
156
+ end
157
+ end
@@ -1,96 +1,96 @@
1
- module Solargraph
2
- class Source
3
- # A factory for generating chains from nodes.
4
- #
5
- class NodeChainer
6
- include Source::NodeMethods
7
-
8
- # @param node [Parser::AST::Node]
9
- # @param filename [String]
10
- def initialize node, filename = nil
11
- @node = node
12
- @filename = filename
13
- end
14
-
15
- # @return [Source::Chain]
16
- def chain
17
- links = generate_links(@node)
18
- Chain.new(links)
19
- end
20
-
21
- class << self
22
- # @param node [Parser::AST::Node]
23
- # @param filename [String]
24
- # @return [Chain]
25
- def chain node, filename = nil
26
- NodeChainer.new(node, filename).chain
27
- end
28
-
29
- # @param code [String]
30
- # @return [Chain]
31
- def load_string(code)
32
- node = Source.parse(code.sub(/\.$/, ''))
33
- chain = NodeChainer.new(node).chain
34
- chain.links.push(Chain::Link.new) if code.end_with?('.')
35
- chain
36
- end
37
- end
38
-
39
- private
40
-
41
- # @param n [Parser::AST::Node]
42
- # @return [Array<Chain::Link>]
43
- def generate_links n
44
- return [] unless n.is_a?(Parser::AST::Node)
45
- return generate_links(n.children[0]) if n.type == :begin
46
- # @todo This might not be right. It's weird either way.
47
- # return generate_links(n.children[2] || n.children[0]) if n.type == :block
48
- result = []
49
- if n.type == :block
50
- result.concat generate_links(n.children[0])
51
- elsif n.type == :send
52
- if n.children[0].is_a?(Parser::AST::Node)
53
- result.concat generate_links(n.children[0])
54
- args = []
55
- n.children[2..-1].each do |c|
56
- args.push NodeChainer.chain(c)
57
- end
58
- result.push Chain::Call.new(n.children[1].to_s, args)
59
- elsif n.children[0].nil?
60
- args = []
61
- n.children[2..-1].each do |c|
62
- args.push NodeChainer.chain(c)
63
- end
64
- result.push Chain::Call.new(n.children[1].to_s, args)
65
- else
66
- raise "No idea what to do with #{n}"
67
- end
68
- elsif n.type == :self
69
- result.push Chain::Head.new('self')
70
- elsif n.type == :zsuper
71
- result.push Chain::Head.new('super')
72
- elsif n.type == :const
73
- const = unpack_name(n)
74
- result.push Chain::Constant.new(const)
75
- elsif [:lvar, :lvasgn].include?(n.type)
76
- result.push Chain::Call.new(n.children[0].to_s)
77
- elsif [:ivar, :ivasgn].include?(n.type)
78
- result.push Chain::InstanceVariable.new(n.children[0].to_s)
79
- elsif [:cvar, :cvasgn].include?(n.type)
80
- result.push Chain::ClassVariable.new(n.children[0].to_s)
81
- elsif [:gvar, :gvasgn].include?(n.type)
82
- result.push Chain::GlobalVariable.new(n.children[0].to_s)
83
- elsif n.type == :or_asgn
84
- result.concat generate_links n.children[1]
85
- elsif [:class, :module, :def, :defs].include?(n.type)
86
- # @todo Undefined or what?
87
- result.push Chain::UNDEFINED_CALL
88
- else
89
- lit = infer_literal_node_type(n)
90
- result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
91
- end
92
- result
93
- end
94
- end
95
- end
96
- end
1
+ module Solargraph
2
+ class Source
3
+ # A factory for generating chains from nodes.
4
+ #
5
+ class NodeChainer
6
+ include Source::NodeMethods
7
+
8
+ # @param node [Parser::AST::Node]
9
+ # @param filename [String]
10
+ def initialize node, filename = nil
11
+ @node = node
12
+ @filename = filename
13
+ end
14
+
15
+ # @return [Source::Chain]
16
+ def chain
17
+ links = generate_links(@node)
18
+ Chain.new(links)
19
+ end
20
+
21
+ class << self
22
+ # @param node [Parser::AST::Node]
23
+ # @param filename [String]
24
+ # @return [Chain]
25
+ def chain node, filename = nil
26
+ NodeChainer.new(node, filename).chain
27
+ end
28
+
29
+ # @param code [String]
30
+ # @return [Chain]
31
+ def load_string(code)
32
+ node = Source.parse(code.sub(/\.$/, ''))
33
+ chain = NodeChainer.new(node).chain
34
+ chain.links.push(Chain::Link.new) if code.end_with?('.')
35
+ chain
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # @param n [Parser::AST::Node]
42
+ # @return [Array<Chain::Link>]
43
+ def generate_links n
44
+ return [] unless n.is_a?(Parser::AST::Node)
45
+ return generate_links(n.children[0]) if n.type == :begin
46
+ # @todo This might not be right. It's weird either way.
47
+ # return generate_links(n.children[2] || n.children[0]) if n.type == :block
48
+ result = []
49
+ if n.type == :block
50
+ result.concat generate_links(n.children[0])
51
+ elsif n.type == :send
52
+ if n.children[0].is_a?(Parser::AST::Node)
53
+ result.concat generate_links(n.children[0])
54
+ args = []
55
+ n.children[2..-1].each do |c|
56
+ args.push NodeChainer.chain(c)
57
+ end
58
+ result.push Chain::Call.new(n.children[1].to_s, args)
59
+ elsif n.children[0].nil?
60
+ args = []
61
+ n.children[2..-1].each do |c|
62
+ args.push NodeChainer.chain(c)
63
+ end
64
+ result.push Chain::Call.new(n.children[1].to_s, args)
65
+ else
66
+ raise "No idea what to do with #{n}"
67
+ end
68
+ elsif n.type == :self
69
+ result.push Chain::Head.new('self')
70
+ elsif n.type == :zsuper
71
+ result.push Chain::Head.new('super')
72
+ elsif n.type == :const
73
+ const = unpack_name(n)
74
+ result.push Chain::Constant.new(const)
75
+ elsif [:lvar, :lvasgn].include?(n.type)
76
+ result.push Chain::Call.new(n.children[0].to_s)
77
+ elsif [:ivar, :ivasgn].include?(n.type)
78
+ result.push Chain::InstanceVariable.new(n.children[0].to_s)
79
+ elsif [:cvar, :cvasgn].include?(n.type)
80
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
81
+ elsif [:gvar, :gvasgn].include?(n.type)
82
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
83
+ elsif n.type == :or_asgn
84
+ result.concat generate_links n.children[1]
85
+ elsif [:class, :module, :def, :defs].include?(n.type)
86
+ # @todo Undefined or what?
87
+ result.push Chain::UNDEFINED_CALL
88
+ else
89
+ lit = infer_literal_node_type(n)
90
+ result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
91
+ end
92
+ result
93
+ end
94
+ end
95
+ end
96
+ end