solargraph 0.19.1 → 0.20.0

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +1 -0
  3. data/lib/solargraph/api_map.rb +29 -4
  4. data/lib/solargraph/api_map/probe.rb +3 -3
  5. data/lib/solargraph/diagnostics.rb +8 -0
  6. data/lib/solargraph/diagnostics/base.rb +12 -0
  7. data/lib/solargraph/diagnostics/require_not_found.rb +23 -0
  8. data/lib/solargraph/diagnostics/rubocop.rb +17 -6
  9. data/lib/solargraph/diagnostics/severities.rb +13 -0
  10. data/lib/solargraph/language_server.rb +5 -4
  11. data/lib/solargraph/language_server/host.rb +113 -19
  12. data/lib/solargraph/language_server/message.rb +2 -0
  13. data/lib/solargraph/language_server/message/base.rb +1 -1
  14. data/lib/solargraph/language_server/message/extended.rb +2 -0
  15. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +38 -0
  16. data/lib/solargraph/language_server/message/extended/document_gems.rb +23 -0
  17. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +6 -7
  18. data/lib/solargraph/language_server/request.rb +14 -0
  19. data/lib/solargraph/library.rb +37 -3
  20. data/lib/solargraph/page.rb +12 -13
  21. data/lib/solargraph/pin/helper.rb +9 -3
  22. data/lib/solargraph/pin/localized.rb +9 -2
  23. data/lib/solargraph/pin/yard_object.rb +2 -3
  24. data/lib/solargraph/shell.rb +6 -0
  25. data/lib/solargraph/source.rb +5 -2
  26. data/lib/solargraph/source/fragment.rb +8 -0
  27. data/lib/solargraph/source/mapper.rb +6 -11
  28. data/lib/solargraph/version.rb +1 -1
  29. data/lib/solargraph/workspace.rb +33 -0
  30. data/lib/solargraph/workspace/config.rb +12 -0
  31. data/lib/solargraph/yard_map.rb +27 -87
  32. data/lib/yard-solargraph.rb +1 -0
  33. metadata +11 -11
@@ -63,6 +63,8 @@ module Solargraph
63
63
  register '$/cancelRequest', CancelRequest
64
64
  register '$/solargraph/document', Extended::Document
65
65
  register '$/solargraph/search', Extended::Search
66
+ register '$/solargraph/checkGemVersion', Extended::CheckGemVersion
67
+ register '$/solargraph/documentGems', Extended::DocumentGems
66
68
  register 'shutdown', Shutdown
67
69
  register 'exit', ExitNotification
68
70
  end
@@ -16,7 +16,7 @@ module Solargraph
16
16
  @id = request['id'].freeze
17
17
  @request = request.freeze
18
18
  @method = request['method'].freeze
19
- @params = request['params'].freeze
19
+ @params = (request['params'] || {}).freeze
20
20
  post_initialize
21
21
  end
22
22
 
@@ -9,6 +9,8 @@ module Solargraph
9
9
  module Extended
10
10
  autoload :Document, 'solargraph/language_server/message/extended/document'
11
11
  autoload :Search, 'solargraph/language_server/message/extended/search'
12
+ autoload :CheckGemVersion, 'solargraph/language_server/message/extended/check_gem_version'
13
+ autoload :DocumentGems, 'solargraph/language_server/message/extended/document_gems'
12
14
  end
13
15
  end
14
16
  end
@@ -0,0 +1,38 @@
1
+ require 'open3'
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ module Message
6
+ module Extended
7
+ # Check if a more recent version of the Solargraph gem is available.
8
+ # Notify the client when an update exists. If the `verbose` parameter
9
+ # is true, notify the client when the gem is up to date.
10
+ #
11
+ class CheckGemVersion < Base
12
+ def process
13
+ o, s = Open3.capture2("gem search solargraph")
14
+ match = o.match(/solargraph \([0-9\.]*?\)/)
15
+ # @todo Error if no match or status code != 0
16
+ available = Gem::Version.new(match[1])
17
+ current = Gem::Version.new(Solargraph::VERSION)
18
+ if available > current
19
+ host.show_message_request "Solagraph gem version #{available} is available.",
20
+ LanguageServer::MessageTypes::INFO,
21
+ ['Update now'] do |result|
22
+ break unless result == 'Update now'
23
+ o, s = Open3.capture2("gem update solargraph")
24
+ if s == 0
25
+ host.show_message 'Successfully updated the Solargraph gem.', LanguageServer::MessageTypes::INFO
26
+ else
27
+ host.show_message 'An error occurred while updating the gem.', LanguageServer::MessageTypes::ERROR
28
+ end
29
+ end
30
+ elsif params['verbose']
31
+ host.show_message "The Solargraph gem is up to date (version #{Solargraph::VERSION})."
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ require 'open3'
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ module Message
6
+ module Extended
7
+ # Update YARD documentation for installed gems. If the `rebuild`
8
+ # parameter is true, rebuild existing yardocs.
9
+ #
10
+ class DocumentGems < Base
11
+ def process
12
+ cmd = "yard gems"
13
+ cmd += " --rebuild" if params['rebuild']
14
+ o, s = Open3.capture2(cmd)
15
+ if s != 0
16
+ host.show_message "An error occurred while building gem documentation.", LanguageServer::MessageTypes::ERROR
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,12 +4,10 @@ module Solargraph
4
4
  module TextDocument
5
5
  class OnTypeFormatting < Base
6
6
  def process
7
- # @todo Temporarily disabled
8
- set_result nil
9
- return
10
- src = host.library.checkout(uri_to_file(params['textDocument']['uri']))
11
- offset = src.get_offset(params['position']['line'], params['position']['character'])
12
- if src.string_at?(offset-1) and params['ch'] == '{' and src.code[offset-2,2] == '#{'
7
+ src = host.send(:library).checkout(uri_to_file(params['textDocument']['uri']))
8
+ fragment = src.fragment_at(params['position']['line'], params['position']['character'] - 1)
9
+ offset = fragment.send(:offset)
10
+ if fragment.string? and params['ch'] == '{' and src.code[offset-1,2] == '#{'
13
11
  set_result(
14
12
  [
15
13
  {
@@ -22,7 +20,8 @@ module Solargraph
22
20
  ]
23
21
  )
24
22
  else
25
- set_result []
23
+ # @todo Is `nil` or `[]` more appropriate here?
24
+ set_result nil
26
25
  end
27
26
  end
28
27
  end
@@ -0,0 +1,14 @@
1
+ module Solargraph
2
+ module LanguageServer
3
+ class Request
4
+ def initialize id, &block
5
+ @id = id
6
+ @block = block
7
+ end
8
+
9
+ def process result
10
+ @block.call(result)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -31,7 +31,16 @@ module Solargraph
31
31
  source_hash.has_key? filename
32
32
  end
33
33
 
34
- # Create a file source to be added to the workspace. The source is ignored
34
+ # True if the specified file is included in the workspace (but not
35
+ # necessarily open).
36
+ #
37
+ # @param filename [String]
38
+ # @return [Boolean]
39
+ def contain? filename
40
+ workspace.has_file?(filename)
41
+ end
42
+
43
+ # Create a file source to be added to the workspace. The file is ignored
35
44
  # if the workspace is not configured to include the file.
36
45
  #
37
46
  # @param filename [String]
@@ -45,12 +54,18 @@ module Solargraph
45
54
  true
46
55
  end
47
56
 
57
+ # Create a file source from a file on disk. The file is ignored if the
58
+ # workspace is not configured to include the file.
59
+ #
60
+ # @param filename [String]
61
+ # @return [Boolean] True if the file was added to the workspace.
48
62
  def create_from_disk filename
49
- return if File.directory?(filename) or !File.exist?(filename)
50
- return unless workspace.would_merge?(filename)
63
+ return false if File.directory?(filename) or !File.exist?(filename)
64
+ return false unless workspace.would_merge?(filename)
51
65
  source = Solargraph::Source.load_string(File.read(filename), filename)
52
66
  workspace.merge(source)
53
67
  api_map.refresh
68
+ true
54
69
  end
55
70
 
56
71
  # Delete a file from the library. Deleting a file will make it unavailable
@@ -198,6 +213,24 @@ module Solargraph
198
213
  source.code
199
214
  end
200
215
 
216
+ # Get diagnostics about a file.
217
+ #
218
+ # @return [Array<Hash>]
219
+ def diagnose filename
220
+ # @todo Only open files get diagnosed. Determine whether anything or
221
+ # everything in the workspace should get diagnosed, or if there should
222
+ # be an option to do so.
223
+ return [] unless open?(filename)
224
+ result = []
225
+ source = read(filename)
226
+ workspace.config.reporters.each do |name|
227
+ reporter = Diagnostics::REPORTERS[name]
228
+ raise DiagnosticsError, "Diagnostics reporter #{name} does not exist" if reporter.nil?
229
+ result.concat reporter.new.diagnose(source, api_map)
230
+ end
231
+ result
232
+ end
233
+
201
234
  # Create a library from a directory.
202
235
  #
203
236
  # @param directory [String] The path to be used for the workspace
@@ -223,6 +256,7 @@ module Solargraph
223
256
  @workspace
224
257
  end
225
258
 
259
+ # @raise [FileNotFoundError] if the file is not open
226
260
  # @param filename [String]
227
261
  # @return [Solargraph::Source]
228
262
  def read filename
@@ -1,21 +1,11 @@
1
1
  require 'ostruct'
2
2
  require 'tilt'
3
- require 'redcarpet'
3
+ require 'kramdown'
4
4
  require 'htmlentities'
5
5
  require 'coderay'
6
6
 
7
7
  module Solargraph
8
8
  class Page
9
- class SolargraphRenderer < Redcarpet::Render::HTML
10
- def normal_text text
11
- HTMLEntities.new.encode(text, :named)
12
- end
13
- def block_code code, language
14
- CodeRay.scan(code, language || :ruby).div
15
- end
16
- end
17
- private_constant :SolargraphRenderer
18
-
19
9
  class Binder < OpenStruct
20
10
  def initialize locals, render_method
21
11
  super(locals)
@@ -31,8 +21,17 @@ module Solargraph
31
21
  helper = Solargraph::Pin::Helper.new
32
22
  html = helper.html_markup_rdoc(text)
33
23
  conv = ReverseMarkdown.convert(html, github_flavored: true)
34
- markdown = Redcarpet::Markdown.new(SolargraphRenderer.new(prettify: true), fenced_code_blocks: true)
35
- markdown.render(conv)
24
+ Kramdown::Document.new(
25
+ conv,
26
+ input: 'GFM',
27
+ entity_output: :symbolic,
28
+ syntax_highlighter_opts: {
29
+ block: {
30
+ line_numbers: false,
31
+ },
32
+ default_lang: :ruby
33
+ },
34
+ ).to_html
36
35
  end
37
36
 
38
37
  def ruby_to_html code
@@ -1,6 +1,4 @@
1
1
  require 'yard'
2
- require 'yard/templates/helpers/markup_helper'
3
- require 'yard/templates/helpers/html_helper'
4
2
 
5
3
  module Solargraph
6
4
  module Pin
@@ -18,10 +16,18 @@ module Solargraph
18
16
  '.'
19
17
  end
20
18
 
19
+ def html_markup_rdoc(text)
20
+ # @todo The :rdoc markup class might not be immediately available.
21
+ # If not, return nil for now under the assumption that the problem
22
+ # will eventually fix itself.
23
+ return nil if markup_class(:rdoc).nil?
24
+ super
25
+ end
26
+
21
27
  def options
22
28
  if @options.nil?
23
29
  @options = YARD::Templates::TemplateOptions.new
24
- @options.type = :rdoc
30
+ @options[:type] = :rdoc
25
31
  end
26
32
  @options
27
33
  end
@@ -2,10 +2,17 @@ module Solargraph
2
2
  module Pin
3
3
  module Localized
4
4
  attr_reader :block
5
+
6
+ # @return [Source::Range]
5
7
  attr_reader :presence
6
8
 
7
- def visible_from?(block, position)
8
- self.block == block and presence.contain?(position)
9
+ # @param other [Pin::Block] The caller's block
10
+ # @param position [Source::Position] The caller's position
11
+ # @return [Boolean]
12
+ def visible_from?(other, position)
13
+ other.filename == filename and
14
+ (other == block or other.named_context == named_context) and
15
+ presence.contain?(position)
9
16
  end
10
17
  end
11
18
  end
@@ -71,14 +71,13 @@ module Solargraph
71
71
  end
72
72
 
73
73
  def location
74
- # @todo Get the location
75
74
  @location
76
75
  end
77
76
 
78
77
  def path
79
78
  code_object.path
80
79
  end
81
-
80
+
82
81
  def namespace
83
82
  # @todo Is this right?
84
83
  code_object.namespace.to_s
@@ -111,7 +110,7 @@ module Solargraph
111
110
  args.push p
112
111
  }
113
112
  args
114
- end
113
+ end
115
114
  end
116
115
  end
117
116
  end
@@ -54,6 +54,7 @@ module Solargraph
54
54
  EventMachine.stop
55
55
  end
56
56
  EventMachine.start_server options[:host], port, Solargraph::LanguageServer::Transport::Socket
57
+ # Emitted for the benefit of clients that start the process on port 0
57
58
  STDERR.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
58
59
  end
59
60
  end
@@ -132,5 +133,10 @@ module Solargraph
132
133
  def clear_cores
133
134
  Solargraph::YardMap::CoreDocs.clear
134
135
  end
136
+
137
+ desc 'reporters', 'Get a list of diagnostics reporters'
138
+ def reporters
139
+ puts Solargraph::Diagnostics::REPORTERS.keys.sort
140
+ end
135
141
  end
136
142
  end
@@ -44,6 +44,8 @@ module Solargraph
44
44
 
45
45
  attr_reader :requires
46
46
 
47
+ attr_reader :domains
48
+
47
49
  attr_reader :locals
48
50
 
49
51
  include NodeMethods
@@ -282,7 +284,8 @@ module Solargraph
282
284
 
283
285
  def all_symbols
284
286
  result = []
285
- result.concat namespace_pin_map.values.flatten
287
+ # result.concat namespace_pin_map.values.flatten
288
+ result.concat namespace_pins.reject{ |pin| pin.name.empty? }
286
289
  result.concat method_pins
287
290
  result.concat constant_pins
288
291
  result
@@ -339,7 +342,7 @@ module Solargraph
339
342
  end
340
343
 
341
344
  def process_parsed node, comments
342
- @pins, @locals, @requires, @symbols, @path_macros = Mapper.map filename, code, node, comments
345
+ @pins, @locals, @requires, @symbols, @path_macros, @domains = Mapper.map filename, code, node, comments
343
346
  @stime = Time.now
344
347
  end
345
348
 
@@ -9,6 +9,8 @@ module Solargraph
9
9
 
10
10
  attr_reader :column
11
11
 
12
+ attr_reader :source
13
+
12
14
  # @param source [Solargraph::Source]
13
15
  # @param line [Integer]
14
16
  # @param column [Integer]
@@ -216,10 +218,16 @@ module Solargraph
216
218
  @locals ||= @source.locals.select{|pin| pin.visible_from?(block, position)}
217
219
  end
218
220
 
221
+ # True if the fragment is a signature that stems from a literal value.
222
+ #
223
+ # @return [Boolean]
219
224
  def base_literal?
220
225
  !base_literal.nil?
221
226
  end
222
227
 
228
+ # The type of literal value at the root of the signature (or nil).
229
+ #
230
+ # @return [String]
223
231
  def base_literal
224
232
  if @base_literal.nil? and !@calculated_literal
225
233
  @calculated_literal = true
@@ -19,6 +19,7 @@ module Solargraph
19
19
  # @todo Stuff that needs to be resolved
20
20
  @variables = []
21
21
  @path_macros = {}
22
+ @domains = []
22
23
 
23
24
  @pins = []
24
25
  @requires = []
@@ -32,7 +33,7 @@ module Solargraph
32
33
  @pins.push Pin::Namespace.new(get_node_location(nil), '', '', nil, :class, :public, nil)
33
34
  process root
34
35
  process_directives
35
- [@pins, @locals, @requires, @symbols, @path_macros]
36
+ [@pins, @locals, @requires, @symbols, @path_macros, @domains]
36
37
  end
37
38
 
38
39
  class << self
@@ -231,7 +232,8 @@ module Solargraph
231
232
  next
232
233
  elsif c.type == :send and c.children[1] == :require
233
234
  if c.children[2].kind_of?(AST::Node) and c.children[2].type == :str
234
- @requires.push c.children[2].children[0].to_s
235
+ # @requires.push c.children[2].children[0].to_s
236
+ @requires.push Solargraph::Pin::Reference.new(get_node_location(c), fqn, c.children[2].children[0].to_s)
235
237
  end
236
238
  elsif c.type == :args
237
239
  if @node_stack.first.type == :block
@@ -263,15 +265,6 @@ module Solargraph
263
265
  stack.pop
264
266
  end
265
267
 
266
- # def path_for node
267
- # path = namespace_for(node) || ''
268
- # mp = (method_pins + attribute_pins).select{|p| p.node == node}.first
269
- # unless mp.nil?
270
- # path += (mp.scope == :instance ? '#' : '.') + mp.name
271
- # end
272
- # path
273
- # end
274
-
275
268
  def get_last_in_stack_not_begin stack
276
269
  index = stack.length - 1
277
270
  last = stack[index]
@@ -379,6 +372,8 @@ module Solargraph
379
372
  here = get_node_start_position(k.node)
380
373
  pin = @pins.select{|pin| [Pin::NAMESPACE, Pin::METHOD].include?(pin.kind) and pin.location.range.contain?(here)}.first
381
374
  @path_macros[pin.path] = v
375
+ elsif d.tag.tag_name == 'domain'
376
+ @domains.push d.tag.text
382
377
  else
383
378
  # STDERR.puts "Nothing to do for directive: #{d}"
384
379
  end