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,169 +1,169 @@
1
- require 'jaro_winkler'
2
-
3
- module Solargraph
4
- # An index of pins and other ApiMap-related data for a Source.
5
- #
6
- class SourceMap
7
- autoload :NodeProcessor, 'solargraph/source_map/node_processor'
8
- autoload :Mapper, 'solargraph/source_map/mapper'
9
- autoload :Clip, 'solargraph/source_map/clip'
10
- autoload :Completion, 'solargraph/source_map/completion'
11
- autoload :Region, 'solargraph/source_map/region'
12
-
13
- # @return [Source]
14
- attr_reader :source
15
-
16
- # @return [Array<Pin::Base>]
17
- attr_reader :pins
18
-
19
- # @return [Array<Pin::Base>]
20
- attr_reader :locals
21
-
22
- # @param source [Source]
23
- # @param pins [Array<Pin::Base>]
24
- # @param locals [Array<Pin::Base>]
25
- def initialize source, pins, locals
26
- # HACK: Keep the library from changing this
27
- @source = source.dup
28
- @pins = pins
29
- @locals = locals
30
- end
31
-
32
- # @return [String]
33
- def filename
34
- source.filename
35
- end
36
-
37
- # @return [String]
38
- def code
39
- source.code
40
- end
41
-
42
- # @return [Array<Pin::Reference::Require>]
43
- def requires
44
- @requires ||= pins.select{|p| p.kind == Pin::REQUIRE_REFERENCE}
45
- end
46
-
47
- # @param position [Position, Array(Integer, Integer)]
48
- # @return [Boolean]
49
- def string_at? position
50
- position = Position.normalize(position)
51
- @source.string_at?(position)
52
- end
53
-
54
- # @param position [Position, Array(Integer, Integer)]
55
- # @return [Boolean]
56
- def comment_at? position
57
- position = Position.normalize(position)
58
- @source.comment_at?(position)
59
- end
60
-
61
- # @return [Array<Pin::Base>]
62
- def document_symbols
63
- @document_symbols ||= pins.select { |pin|
64
- [Pin::ATTRIBUTE, Pin::CONSTANT, Pin::METHOD, Pin::NAMESPACE].include?(pin.kind) and !pin.path.empty?
65
- }
66
- end
67
-
68
- # @param query [String]
69
- # @return [Array<Pin::Base>]
70
- def query_symbols query
71
- document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
72
- end
73
-
74
- # @param position [Position]
75
- # @return [Solargraph::SourceMap::Fragment]
76
- def cursor_at position
77
- Source::Cursor.new(source, position)
78
- end
79
-
80
- # @param path [String]
81
- # @return [Pin::Base]
82
- def first_pin path
83
- pins.select { |p| p.path == path }.first
84
- end
85
-
86
- # @param location [Solargraph::Location]
87
- # @return [Array<Solargraph::Pin::Base>]
88
- def locate_pins location
89
- # return nil unless location.start_with?("#{filename}:")
90
- pins.select { |pin| pin.location == location }
91
- end
92
-
93
- def locate_named_path_pin line, character
94
- _locate_pin line, character, Pin::NAMESPACE, Pin::METHOD
95
- end
96
-
97
- def locate_block_pin line, character
98
- _locate_pin line, character, Pin::NAMESPACE, Pin::METHOD, Pin::BLOCK
99
- end
100
-
101
- # @param other_map [SourceMap]
102
- # @return [Boolean]
103
- def try_merge! other_map
104
- return false if pins.length != other_map.pins.length || locals.length != other_map.locals.length || requires.map(&:name).uniq.sort != other_map.requires.map(&:name).uniq.sort
105
- pins.each_index do |i|
106
- return false unless pins[i].try_merge!(other_map.pins[i])
107
- end
108
- locals.each_index do |i|
109
- return false unless locals[i].try_merge!(other_map.locals[i])
110
- end
111
- @source = other_map.source
112
- true
113
- end
114
-
115
- # @param name [String]
116
- # @return [Array<Location>]
117
- def references name
118
- source.references name
119
- end
120
-
121
- class << self
122
- # @param filename [String]
123
- # @return [SourceMap]
124
- def load filename
125
- source = Solargraph::Source.load(filename)
126
- SourceMap.map(source)
127
- end
128
-
129
- # @param code [String]
130
- # @param filename [String, nil]
131
- # @return [SourceMap]
132
- def load_string code, filename = nil
133
- source = Solargraph::Source.load_string(code, filename)
134
- SourceMap.map(source)
135
- end
136
-
137
- # @param source [Source]
138
- # @return [SourceMap]
139
- def map source
140
- result = SourceMap::Mapper.map(source)
141
- new(source, *result)
142
- end
143
- end
144
-
145
- private
146
-
147
- # @param line [Integer]
148
- # @param character [Integer]
149
- # @param *kinds [Array<Symbol>]
150
- # @return [Pin::Base]
151
- def _locate_pin line, character, *kinds
152
- position = Position.new(line, character)
153
- found = nil
154
- pins.each do |pin|
155
- found = pin if (kinds.empty? || kinds.include?(pin.kind)) && pin.location.range.contain?(position)
156
- break if pin.location.range.start.line > line
157
- end
158
- # @todo Assuming the root pin is always valid
159
- found || pins.first
160
- end
161
-
162
- # @param str1 [String]
163
- # @param str2 [String]
164
- # @return [Boolean]
165
- def fuzzy_string_match str1, str2
166
- JaroWinkler.distance(str1, str2) > 0.6
167
- end
168
- end
169
- end
1
+ require 'jaro_winkler'
2
+
3
+ module Solargraph
4
+ # An index of pins and other ApiMap-related data for a Source.
5
+ #
6
+ class SourceMap
7
+ autoload :NodeProcessor, 'solargraph/source_map/node_processor'
8
+ autoload :Mapper, 'solargraph/source_map/mapper'
9
+ autoload :Clip, 'solargraph/source_map/clip'
10
+ autoload :Completion, 'solargraph/source_map/completion'
11
+ autoload :Region, 'solargraph/source_map/region'
12
+
13
+ # @return [Source]
14
+ attr_reader :source
15
+
16
+ # @return [Array<Pin::Base>]
17
+ attr_reader :pins
18
+
19
+ # @return [Array<Pin::Base>]
20
+ attr_reader :locals
21
+
22
+ # @param source [Source]
23
+ # @param pins [Array<Pin::Base>]
24
+ # @param locals [Array<Pin::Base>]
25
+ def initialize source, pins, locals
26
+ # HACK: Keep the library from changing this
27
+ @source = source.dup
28
+ @pins = pins
29
+ @locals = locals
30
+ end
31
+
32
+ # @return [String]
33
+ def filename
34
+ source.filename
35
+ end
36
+
37
+ # @return [String]
38
+ def code
39
+ source.code
40
+ end
41
+
42
+ # @return [Array<Pin::Reference::Require>]
43
+ def requires
44
+ @requires ||= pins.select{|p| p.kind == Pin::REQUIRE_REFERENCE}
45
+ end
46
+
47
+ # @param position [Position, Array(Integer, Integer)]
48
+ # @return [Boolean]
49
+ def string_at? position
50
+ position = Position.normalize(position)
51
+ @source.string_at?(position)
52
+ end
53
+
54
+ # @param position [Position, Array(Integer, Integer)]
55
+ # @return [Boolean]
56
+ def comment_at? position
57
+ position = Position.normalize(position)
58
+ @source.comment_at?(position)
59
+ end
60
+
61
+ # @return [Array<Pin::Base>]
62
+ def document_symbols
63
+ @document_symbols ||= pins.select { |pin|
64
+ [Pin::ATTRIBUTE, Pin::CONSTANT, Pin::METHOD, Pin::NAMESPACE].include?(pin.kind) and !pin.path.empty?
65
+ }
66
+ end
67
+
68
+ # @param query [String]
69
+ # @return [Array<Pin::Base>]
70
+ def query_symbols query
71
+ document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
72
+ end
73
+
74
+ # @param position [Position]
75
+ # @return [Solargraph::SourceMap::Fragment]
76
+ def cursor_at position
77
+ Source::Cursor.new(source, position)
78
+ end
79
+
80
+ # @param path [String]
81
+ # @return [Pin::Base]
82
+ def first_pin path
83
+ pins.select { |p| p.path == path }.first
84
+ end
85
+
86
+ # @param location [Solargraph::Location]
87
+ # @return [Array<Solargraph::Pin::Base>]
88
+ def locate_pins location
89
+ # return nil unless location.start_with?("#{filename}:")
90
+ pins.select { |pin| pin.location == location }
91
+ end
92
+
93
+ def locate_named_path_pin line, character
94
+ _locate_pin line, character, Pin::NAMESPACE, Pin::METHOD
95
+ end
96
+
97
+ def locate_block_pin line, character
98
+ _locate_pin line, character, Pin::NAMESPACE, Pin::METHOD, Pin::BLOCK
99
+ end
100
+
101
+ # @param other_map [SourceMap]
102
+ # @return [Boolean]
103
+ def try_merge! other_map
104
+ return false if pins.length != other_map.pins.length || locals.length != other_map.locals.length || requires.map(&:name).uniq.sort != other_map.requires.map(&:name).uniq.sort
105
+ pins.each_index do |i|
106
+ return false unless pins[i].try_merge!(other_map.pins[i])
107
+ end
108
+ locals.each_index do |i|
109
+ return false unless locals[i].try_merge!(other_map.locals[i])
110
+ end
111
+ @source = other_map.source
112
+ true
113
+ end
114
+
115
+ # @param name [String]
116
+ # @return [Array<Location>]
117
+ def references name
118
+ source.references name
119
+ end
120
+
121
+ class << self
122
+ # @param filename [String]
123
+ # @return [SourceMap]
124
+ def load filename
125
+ source = Solargraph::Source.load(filename)
126
+ SourceMap.map(source)
127
+ end
128
+
129
+ # @param code [String]
130
+ # @param filename [String, nil]
131
+ # @return [SourceMap]
132
+ def load_string code, filename = nil
133
+ source = Solargraph::Source.load_string(code, filename)
134
+ SourceMap.map(source)
135
+ end
136
+
137
+ # @param source [Source]
138
+ # @return [SourceMap]
139
+ def map source
140
+ result = SourceMap::Mapper.map(source)
141
+ new(source, *result)
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ # @param line [Integer]
148
+ # @param character [Integer]
149
+ # @param *kinds [Array<Symbol>]
150
+ # @return [Pin::Base]
151
+ def _locate_pin line, character, *kinds
152
+ position = Position.new(line, character)
153
+ found = nil
154
+ pins.each do |pin|
155
+ found = pin if (kinds.empty? || kinds.include?(pin.kind)) && pin.location.range.contain?(position)
156
+ break if pin.location.range.start.line > line
157
+ end
158
+ # @todo Assuming the root pin is always valid
159
+ found || pins.first
160
+ end
161
+
162
+ # @param str1 [String]
163
+ # @param str2 [String]
164
+ # @return [Boolean]
165
+ def fuzzy_string_match str1, str2
166
+ JaroWinkler.distance(str1, str2) > 0.6
167
+ end
168
+ end
169
+ end
@@ -1,145 +1,145 @@
1
- module Solargraph
2
- class SourceMap
3
- # A static analysis tool for obtaining definitions, completions,
4
- # signatures, and type inferences from a cursor.
5
- #
6
- class Clip
7
- # @param api_map [ApiMap]
8
- # @param cursor [Source::Cursor]
9
- def initialize api_map, cursor
10
- @api_map = api_map
11
- @cursor = cursor
12
- end
13
-
14
- # @return [Array<Pin::Base>]
15
- def define
16
- return [] if cursor.comment? || cursor.chain.literal?
17
- result = cursor.chain.define(api_map, context_pin, locals)
18
- result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
19
- result
20
- end
21
-
22
- # @return [Completion]
23
- def complete
24
- return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
25
- return Completion.new([], cursor.range) if cursor.chain.literal? || cursor.comment?
26
- result = []
27
- if cursor.chain.constant? || cursor.start_of_constant?
28
- if cursor.chain.undefined?
29
- type = cursor.chain.base.infer(api_map, context_pin, locals)
30
- else
31
- full = cursor.chain.links.first.word
32
- if full.include?('::') && cursor.chain.links.length == 1
33
- type = ComplexType.try_parse(full.split('::')[0..-2].join('::'))
34
- elsif cursor.chain.links.length > 1
35
- type = ComplexType.try_parse(full)
36
- else
37
- type = ComplexType::UNDEFINED
38
- end
39
- end
40
- result.concat api_map.get_constants(type.undefined? ? '' : type.namespace, cursor.start_of_constant? ? '' : context_pin.context.namespace)
41
- else
42
- type = cursor.chain.base.infer(api_map, context_pin, locals)
43
- result.concat api_map.get_complex_type_methods(type, context_pin.context.namespace, cursor.chain.links.length == 1)
44
- if cursor.chain.links.length == 1
45
- if cursor.word.start_with?('@@')
46
- return package_completions(api_map.get_class_variable_pins(context_pin.context.namespace))
47
- elsif cursor.word.start_with?('@')
48
- return package_completions(api_map.get_instance_variable_pins(context_pin.context.namespace, context_pin.context.scope))
49
- elsif cursor.word.start_with?('$')
50
- return package_completions(api_map.get_global_variable_pins)
51
- end
52
- result.concat locals
53
- result.concat api_map.get_constants('', context_pin.context.namespace)
54
- result.concat api_map.get_methods(context_pin.context.namespace, scope: context_pin.context.scope, visibility: [:public, :private, :protected])
55
- result.concat api_map.get_methods('Kernel')
56
- result.concat ApiMap.keywords
57
- result.concat yielded_self_pins
58
- end
59
- end
60
- package_completions(result)
61
- end
62
-
63
- # @return [Array<Pin::Base>]
64
- def signify
65
- return [] unless cursor.argument?
66
- clip = Clip.new(api_map, cursor.recipient)
67
- clip.define.select{|pin| pin.kind == Pin::METHOD}
68
- end
69
-
70
- # @return [ComplexType]
71
- def infer
72
- cursor.chain.infer(api_map, context_pin, locals)
73
- end
74
-
75
- # Get an array of all the locals that are visible from the cursors's
76
- # position. Locals can be local variables, method parameters, or block
77
- # parameters. The array starts with the nearest local pin.
78
- #
79
- # @return [Array<Solargraph::Pin::Base>]
80
- def locals
81
- loc_pos = context_pin.location.range.contain?(cursor.position) ? cursor.position : context_pin.location.range.ending
82
- adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
83
- @locals ||= source_map.locals.select { |pin|
84
- pin.visible_from?(block, adj_pos)
85
- }.reverse
86
- end
87
-
88
- private
89
-
90
- # @return [ApiMap]
91
- attr_reader :api_map
92
-
93
- # @return [Source::Cursor]
94
- attr_reader :cursor
95
-
96
- # @return [SourceMap]
97
- def source_map
98
- @source_map ||= api_map.source_map(cursor.filename)
99
- end
100
-
101
- # @return [Solargraph::Pin::Base]
102
- def block
103
- @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
104
- end
105
-
106
- # The context at the current position.
107
- #
108
- # @return [Pin::Base]
109
- def context_pin
110
- @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
111
- end
112
-
113
- # @return [Array<Pin::Base>]
114
- def yielded_self_pins
115
- return [] unless block.is_a?(Pin::Block) && block.receiver
116
- chain = Solargraph::Source::NodeChainer.chain(block.receiver, source_map.source.filename)
117
- receiver_pin = chain.define(api_map, context_pin, locals).first
118
- return [] if receiver_pin.nil?
119
- result = []
120
- ys = receiver_pin.docstring.tag(:yieldself)
121
- unless ys.nil? || ys.types.empty?
122
- ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
123
- result.concat api_map.get_complex_type_methods(ysct, ysct.namespace, true)
124
- end
125
- ys = receiver_pin.docstring.tag(:yieldpublic)
126
- unless ys.nil? || ys.types.empty?
127
- ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
128
- result.concat api_map.get_complex_type_methods(ysct, '', false)
129
- end
130
- result
131
- end
132
-
133
- # @param result [Array<Pin::Base>]
134
- # @return [Completion]
135
- def package_completions result
136
- frag_start = cursor.start_of_word.to_s.downcase
137
- filtered = result.uniq(&:name).select { |s|
138
- s.name.downcase.start_with?(frag_start) &&
139
- (s.kind != Pin::METHOD || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
140
- }
141
- Completion.new(filtered, cursor.range)
142
- end
143
- end
144
- end
145
- end
1
+ module Solargraph
2
+ class SourceMap
3
+ # A static analysis tool for obtaining definitions, completions,
4
+ # signatures, and type inferences from a cursor.
5
+ #
6
+ class Clip
7
+ # @param api_map [ApiMap]
8
+ # @param cursor [Source::Cursor]
9
+ def initialize api_map, cursor
10
+ @api_map = api_map
11
+ @cursor = cursor
12
+ end
13
+
14
+ # @return [Array<Pin::Base>]
15
+ def define
16
+ return [] if cursor.comment? || cursor.chain.literal?
17
+ result = cursor.chain.define(api_map, context_pin, locals)
18
+ result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
19
+ result
20
+ end
21
+
22
+ # @return [Completion]
23
+ def complete
24
+ return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
25
+ return Completion.new([], cursor.range) if cursor.chain.literal? || cursor.comment?
26
+ result = []
27
+ if cursor.chain.constant? || cursor.start_of_constant?
28
+ if cursor.chain.undefined?
29
+ type = cursor.chain.base.infer(api_map, context_pin, locals)
30
+ else
31
+ full = cursor.chain.links.first.word
32
+ if full.include?('::') && cursor.chain.links.length == 1
33
+ type = ComplexType.try_parse(full.split('::')[0..-2].join('::'))
34
+ elsif cursor.chain.links.length > 1
35
+ type = ComplexType.try_parse(full)
36
+ else
37
+ type = ComplexType::UNDEFINED
38
+ end
39
+ end
40
+ result.concat api_map.get_constants(type.undefined? ? '' : type.namespace, cursor.start_of_constant? ? '' : context_pin.context.namespace)
41
+ else
42
+ type = cursor.chain.base.infer(api_map, context_pin, locals)
43
+ result.concat api_map.get_complex_type_methods(type, context_pin.context.namespace, cursor.chain.links.length == 1)
44
+ if cursor.chain.links.length == 1
45
+ if cursor.word.start_with?('@@')
46
+ return package_completions(api_map.get_class_variable_pins(context_pin.context.namespace))
47
+ elsif cursor.word.start_with?('@')
48
+ return package_completions(api_map.get_instance_variable_pins(context_pin.context.namespace, context_pin.context.scope))
49
+ elsif cursor.word.start_with?('$')
50
+ return package_completions(api_map.get_global_variable_pins)
51
+ end
52
+ result.concat locals
53
+ result.concat api_map.get_constants('', context_pin.context.namespace)
54
+ result.concat api_map.get_methods(context_pin.context.namespace, scope: context_pin.context.scope, visibility: [:public, :private, :protected])
55
+ result.concat api_map.get_methods('Kernel')
56
+ result.concat ApiMap.keywords
57
+ result.concat yielded_self_pins
58
+ end
59
+ end
60
+ package_completions(result)
61
+ end
62
+
63
+ # @return [Array<Pin::Base>]
64
+ def signify
65
+ return [] unless cursor.argument?
66
+ clip = Clip.new(api_map, cursor.recipient)
67
+ clip.define.select{|pin| pin.kind == Pin::METHOD}
68
+ end
69
+
70
+ # @return [ComplexType]
71
+ def infer
72
+ cursor.chain.infer(api_map, context_pin, locals)
73
+ end
74
+
75
+ # Get an array of all the locals that are visible from the cursors's
76
+ # position. Locals can be local variables, method parameters, or block
77
+ # parameters. The array starts with the nearest local pin.
78
+ #
79
+ # @return [Array<Solargraph::Pin::Base>]
80
+ def locals
81
+ loc_pos = context_pin.location.range.contain?(cursor.position) ? cursor.position : context_pin.location.range.ending
82
+ adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
83
+ @locals ||= source_map.locals.select { |pin|
84
+ pin.visible_from?(block, adj_pos)
85
+ }.reverse
86
+ end
87
+
88
+ private
89
+
90
+ # @return [ApiMap]
91
+ attr_reader :api_map
92
+
93
+ # @return [Source::Cursor]
94
+ attr_reader :cursor
95
+
96
+ # @return [SourceMap]
97
+ def source_map
98
+ @source_map ||= api_map.source_map(cursor.filename)
99
+ end
100
+
101
+ # @return [Solargraph::Pin::Base]
102
+ def block
103
+ @block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
104
+ end
105
+
106
+ # The context at the current position.
107
+ #
108
+ # @return [Pin::Base]
109
+ def context_pin
110
+ @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
111
+ end
112
+
113
+ # @return [Array<Pin::Base>]
114
+ def yielded_self_pins
115
+ return [] unless block.is_a?(Pin::Block) && block.receiver
116
+ chain = Solargraph::Source::NodeChainer.chain(block.receiver, source_map.source.filename)
117
+ receiver_pin = chain.define(api_map, context_pin, locals).first
118
+ return [] if receiver_pin.nil?
119
+ result = []
120
+ ys = receiver_pin.docstring.tag(:yieldself)
121
+ unless ys.nil? || ys.types.empty?
122
+ ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
123
+ result.concat api_map.get_complex_type_methods(ysct, ysct.namespace, true)
124
+ end
125
+ ys = receiver_pin.docstring.tag(:yieldpublic)
126
+ unless ys.nil? || ys.types.empty?
127
+ ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
128
+ result.concat api_map.get_complex_type_methods(ysct, '', false)
129
+ end
130
+ result
131
+ end
132
+
133
+ # @param result [Array<Pin::Base>]
134
+ # @return [Completion]
135
+ def package_completions result
136
+ frag_start = cursor.start_of_word.to_s.downcase
137
+ filtered = result.uniq(&:name).select { |s|
138
+ s.name.downcase.start_with?(frag_start) &&
139
+ (s.kind != Pin::METHOD || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
140
+ }
141
+ Completion.new(filtered, cursor.range)
142
+ end
143
+ end
144
+ end
145
+ end