solargraph 0.18.2 → 0.18.3

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solargraph.rb +33 -28
  3. data/lib/solargraph/api_map.rb +997 -1044
  4. data/lib/solargraph/api_map/source_to_yard.rb +4 -3
  5. data/lib/solargraph/diagnostics/rubocop.rb +4 -3
  6. data/lib/solargraph/language_server/host.rb +140 -70
  7. data/lib/solargraph/language_server/message/base.rb +1 -0
  8. data/lib/solargraph/language_server/message/client.rb +6 -2
  9. data/lib/solargraph/language_server/message/text_document/completion.rb +34 -39
  10. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  11. data/lib/solargraph/language_server/message/text_document/did_close.rb +1 -0
  12. data/lib/solargraph/language_server/message/text_document/did_save.rb +1 -3
  13. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +1 -1
  14. data/lib/solargraph/language_server/message/text_document/hover.rb +25 -30
  15. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +1 -1
  16. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +8 -7
  17. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +1 -1
  18. data/lib/solargraph/language_server/transport/socket.rb +15 -17
  19. data/lib/solargraph/library.rb +34 -16
  20. data/lib/solargraph/node_methods.rb +96 -96
  21. data/lib/solargraph/pin.rb +1 -0
  22. data/lib/solargraph/pin/base.rb +2 -1
  23. data/lib/solargraph/pin/base_variable.rb +45 -5
  24. data/lib/solargraph/pin/block_parameter.rb +5 -2
  25. data/lib/solargraph/pin/method.rb +22 -0
  26. data/lib/solargraph/pin/namespace.rb +32 -2
  27. data/lib/solargraph/pin/reference.rb +21 -0
  28. data/lib/solargraph/pin/yard_object.rb +9 -0
  29. data/lib/solargraph/shell.rb +136 -136
  30. data/lib/solargraph/source.rb +134 -188
  31. data/lib/solargraph/source/change.rb +70 -0
  32. data/lib/solargraph/source/fragment.rb +120 -66
  33. data/lib/solargraph/source/position.rb +41 -0
  34. data/lib/solargraph/source/updater.rb +48 -0
  35. data/lib/solargraph/version.rb +3 -3
  36. data/lib/solargraph/workspace/config.rb +4 -9
  37. data/lib/solargraph/yard_map/core_docs.rb +0 -1
  38. metadata +5 -2
@@ -19,5 +19,6 @@ module Solargraph
19
19
  autoload :Parameter, 'solargraph/pin/parameter'
20
20
  autoload :MethodParameter, 'solargraph/pin/method_parameter'
21
21
  autoload :BlockParameter, 'solargraph/pin/block_parameter'
22
+ autoload :Reference, 'solargraph/pin/reference'
22
23
  end
23
24
  end
@@ -99,6 +99,7 @@ module Solargraph
99
99
  def documentation
100
100
  if @documentation.nil? and !docstring.nil?
101
101
  @documentation = ReverseMarkdown.convert(helper.html_markup_rdoc(docstring), github_flavored: true)
102
+ @documentation.strip!
102
103
  end
103
104
  @documentation
104
105
  end
@@ -124,7 +125,7 @@ module Solargraph
124
125
  end
125
126
 
126
127
  def identifier
127
- @identifier ||= "#{path || location}"
128
+ @identifier ||= "#{path}|#{name}"
128
129
  end
129
130
 
130
131
  def variable?
@@ -6,6 +6,7 @@ module Solargraph
6
6
  def initialize source, node, namespace
7
7
  super
8
8
  @tried_to_detect_return_type = false
9
+ @tried_to_resolve_return_type = false
9
10
  end
10
11
 
11
12
  def name
@@ -20,7 +21,7 @@ module Solargraph
20
21
  if @return_type.nil? and !@tried_to_detect_return_type
21
22
  @tried_to_detect_return_type = true
22
23
  if docstring.nil?
23
- @return_type ||= literal_from_assignment
24
+ @return_type ||= infer_literal_node_type(assignment_node)
24
25
  else
25
26
  tag = docstring.tag(:type)
26
27
  @return_type = tag.types[0] unless tag.nil?
@@ -41,11 +42,29 @@ module Solargraph
41
42
  @signature ||= resolve_node_signature(assignment_node)
42
43
  end
43
44
 
45
+ def calculated_signature
46
+ if @calculated_signature.nil?
47
+ if signature.empty?
48
+ type = infer_literal_node_type(assignment_node)
49
+ @calculated_signature = "#{type}.new" unless type.nil?
50
+ end
51
+ @calculated_signature ||= signature
52
+ end
53
+ @calculated_signature
54
+ end
55
+
44
56
  # @param api_map [Solargraph::ApiMap]
45
57
  def resolve api_map
46
- if return_type.nil?
58
+ if return_type.nil? and !@tried_to_resolve_return_type
59
+ @tried_to_detect_return_type = true
47
60
  return nil if signature.nil? or signature.empty? or signature == name or signature.split('.').first.strip == name
48
- @return_type = api_map.infer_signature_type(signature, namespace, call_node: node)
61
+ # @todo This should be able to resolve signatures that start with local variables
62
+ macro_type = nil
63
+ # pin = api_map.tail_pin(signature, namespace, :class, [:public, :private, :protected])
64
+ # unless pin.nil? or !pin.method?
65
+ # macro_type = get_return_type_from_macro(pin, assignment_node)
66
+ # end
67
+ @return_type = macro_type || api_map.infer_type(signature, namespace, scope: :class)
49
68
  end
50
69
  end
51
70
 
@@ -55,8 +74,29 @@ module Solargraph
55
74
 
56
75
  private
57
76
 
58
- def literal_from_assignment
59
- infer_literal_node_type(assignment_node)
77
+ def get_call_arguments node
78
+ return get_call_arguments(node.children[1]) if [:ivasgn, :cvasgn, :lvasgn].include?(node.type)
79
+ return [] unless node.type == :send
80
+ result = []
81
+ node.children[2..-1].each do |c|
82
+ result.push unpack_name(c)
83
+ end
84
+ result
85
+ end
86
+
87
+ def get_return_type_from_macro method_pin, call_node
88
+ return nil if method_pin.docstring.nil?
89
+ type = nil
90
+ all = YARD::Docstring.parser.parse(method_pin.docstring.all).directives
91
+ macro = all.select{|m| m.tag.tag_name == 'macro'}.first
92
+ return nil if macro.nil?
93
+ macstring = YARD::Docstring.parser.parse(macro.tag.text).to_docstring
94
+ rt = macstring.tag(:return)
95
+ unless rt.nil? or rt.types.nil?
96
+ args = get_call_arguments(call_node)
97
+ type = "#{args[rt.types[0][1..-1].to_i-1]}"
98
+ end
99
+ type
60
100
  end
61
101
  end
62
102
  end
@@ -21,12 +21,15 @@ module Solargraph
21
21
  def resolve api_map
22
22
  return unless return_type.nil?
23
23
  signature = resolve_node_signature(@tree[0].children[0])
24
- meth = api_map.infer_signature_pins(signature, namespace, :class, node).first
24
+ # @todo Hardcoding :class scope might not be appropriate
25
+ # meth = api_map.infer_pin(signature, namespace, :class, [:public, :private, :protected], true)
26
+ meth = api_map.tail_pin(signature, namespace, :class, [:public, :private, :protected])
25
27
  return nil if meth.nil?
26
28
  if (Solargraph::CoreFills::METHODS_WITH_YIELDPARAM_SUBTYPES.include?(meth.path))
27
29
  base = signature.split('.')[0..-2].join('.')
28
30
  return nil if base.nil? or base.empty?
29
- bmeth = api_map.infer_signature_pins(base, namespace, :class, node).first
31
+ # @todo Maybe use a fragment so this picks up local variables
32
+ bmeth = api_map.tail_pin(base, namespace, :class, [:public, :private, :protected])
30
33
  return nil if bmeth.nil?
31
34
  subtypes = get_subtypes(bmeth.return_type)
32
35
  @return_type = api_map.find_fully_qualified_namespace(subtypes[0], namespace)
@@ -43,6 +43,28 @@ module Solargraph
43
43
  @parameters ||= get_method_args
44
44
  end
45
45
 
46
+ def documentation
47
+ if @documentation.nil?
48
+ @documentation ||= super || ''
49
+ unless docstring.nil?
50
+ param_tags = docstring.tags(:param)
51
+ unless param_tags.nil? or param_tags.empty?
52
+ @documentation += "\n\n"
53
+ @documentation += "Params:\n"
54
+ lines = []
55
+ param_tags.each do |p|
56
+ l = "* #{p.name}"
57
+ l += " [#{p.types.join(', ')}]" unless p.types.empty?
58
+ l += " #{p.text}"
59
+ lines.push l
60
+ end
61
+ @documentation += lines.join("\n")
62
+ end
63
+ end
64
+ end
65
+ @documentation
66
+ end
67
+
46
68
  # @todo This method was temporarily migrated directly from Suggestion
47
69
  # @return [Array<String>]
48
70
  def params
@@ -5,13 +5,26 @@ module Solargraph
5
5
 
6
6
  attr_reader :visibility
7
7
 
8
- def initialize source, node, namespace, visibility
8
+ def initialize source, node, namespace, visibility, superclass = nil
9
9
  super(source, node, namespace)
10
10
  @visibility = visibility
11
+ @superclass_reference = Reference.new(self, superclass) unless superclass.nil?
12
+ end
13
+
14
+ def reference_include name
15
+ include_references.push Reference.new(self, name)
16
+ end
17
+
18
+ def reference_extend name
19
+ extend_references.push Reference.new(self, name)
20
+ end
21
+
22
+ def reference_superclass name
23
+ @superclass_reference = Reference.new(self, name)
11
24
  end
12
25
 
13
26
  def name
14
- @name ||= pack_name(node.children[0]).last.to_s
27
+ @name ||= (node.type == :source ? '' : pack_name(node.children[0]).last.to_s)
15
28
  end
16
29
 
17
30
  def path
@@ -22,11 +35,28 @@ module Solargraph
22
35
  @kind ||= (node.type == :class ? Solargraph::LanguageServer::CompletionItemKinds::CLASS : Solargraph::LanguageServer::CompletionItemKinds::MODULE)
23
36
  end
24
37
 
38
+ def include_references
39
+ @include_references ||= []
40
+ end
41
+
42
+ def extend_references
43
+ @extend_references ||= []
44
+ end
45
+
46
+ def superclass_reference
47
+ @superclass_reference
48
+ end
49
+
25
50
  # @return [Symbol] :class or :module
26
51
  def type
27
52
  node.type
28
53
  end
29
54
 
55
+ def location
56
+ return "#{source.filename}:0" if name.empty?
57
+ super
58
+ end
59
+
30
60
  def return_type
31
61
  @return_type ||= (node.type == :class ? 'Class' : 'Module') + "<#{path}>"
32
62
  end
@@ -0,0 +1,21 @@
1
+ module Solargraph
2
+ module Pin
3
+ class Reference
4
+ attr_reader :pin
5
+ attr_reader :name
6
+
7
+ def initialize pin, name
8
+ @pin = pin
9
+ @name = name
10
+ @resolved = false
11
+ end
12
+
13
+ def resolve api_map
14
+ unless @resolved
15
+ @resolved = true
16
+ @name = api_map.find_fully_qualified_namespace(@name, pin.namespace)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -81,6 +81,15 @@ module Solargraph
81
81
  completion_item_kind == Solargraph::LanguageServer::CompletionItemKinds::METHOD
82
82
  end
83
83
 
84
+ def visibility
85
+ :public #@todo Resolve this
86
+ end
87
+
88
+ def scope
89
+ return nil unless code_object.is_a?(YARD::CodeObjects::MethodObject)
90
+ code_object.scope
91
+ end
92
+
84
93
  private
85
94
 
86
95
  def get_method_args
@@ -1,136 +1,136 @@
1
- require 'thor'
2
- require 'json'
3
- require 'fileutils'
4
- require 'rubygems/package'
5
- require 'zlib'
6
- require 'eventmachine'
7
-
8
- module Solargraph
9
- class Shell < Thor
10
- include Solargraph::ServerMethods
11
-
12
- map %w[--version -v] => :version
13
-
14
- desc "--version, -v", "Print the version"
15
- def version
16
- puts Solargraph::VERSION
17
- end
18
-
19
- desc 'server', 'Start a Solargraph server'
20
- option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7657
21
- option :views, type: :string, aliases: :v, desc: 'The view template directory', default: nil
22
- option :files, type: :string, aliases: :f, desc: 'The public files directory', default: nil
23
- def server
24
- port = options[:port]
25
- port = available_port if port.zero?
26
- Solargraph::Server.set :port, port
27
- Solargraph::Server.set :views, options[:views] unless options[:views].nil?
28
- Solargraph::Server.set :public_folder, options[:files] unless options[:files].nil?
29
- my_pid = nil
30
- Solargraph::Server.run! do
31
- # This line should not be necessary with WEBrick
32
- #STDERR.puts "Solargraph server pid=#{Process.pid} port=#{port}"
33
- my_pid = Process.pid
34
- Signal.trap("INT") do
35
- Solargraph::Server.stop!
36
- end
37
- Signal.trap("TERM") do
38
- Solargraph::Server.stop!
39
- end
40
- end
41
- end
42
-
43
- desc 'socket', 'Run a Solargraph socket server'
44
- option :host, type: :string, aliases: :h, desc: 'The server host', default: '127.0.0.1'
45
- option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7658
46
- def socket
47
- port = options[:port]
48
- port = available_port if port.zero?
49
- EventMachine.run do
50
- Signal.trap("INT") do
51
- EventMachine.stop
52
- end
53
- Signal.trap("TERM") do
54
- EventMachine.stop
55
- end
56
- EventMachine.start_server options[:host], port, Solargraph::LanguageServer::Transport::Socket
57
- STDERR.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
58
- end
59
- end
60
-
61
- desc 'suggest', 'Get code suggestions for the provided input'
62
- long_desc <<-LONGDESC
63
- Analyze a Ruby file and output a list of code suggestions in JSON format.
64
- LONGDESC
65
- option :line, type: :numeric, aliases: :l, desc: 'Zero-based line number', required: true
66
- option :column, type: :numeric, aliases: [:c, :col], desc: 'Zero-based column number', required: true
67
- option :filename, type: :string, aliases: :f, desc: 'File name', required: false
68
- def suggest(*filenames)
69
- STDERR.puts "WARNING: The `solargraph suggest` command is a candidate for deprecation. It will either change drastically or not exist in a future version."
70
- # HACK: The ARGV array needs to be manipulated for ARGF.read to work
71
- ARGV.clear
72
- ARGV.concat filenames
73
- text = ARGF.read
74
- filename = options[:filename] || filenames[0]
75
- begin
76
- code_map = CodeMap.new(code: text, filename: filename)
77
- offset = code_map.get_offset(options[:line], options[:column])
78
- sugg = code_map.suggest_at(offset, filtered: true)
79
- result = { "status" => "ok", "suggestions" => sugg }.to_json
80
- STDOUT.puts result
81
- rescue Exception => e
82
- STDERR.puts e
83
- STDERR.puts e.backtrace.join("\n")
84
- result = { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
85
- STDOUT.puts result
86
- end
87
- end
88
-
89
- desc 'config [DIRECTORY]', 'Create or overwrite a default configuration file'
90
- option :extensions, type: :boolean, aliases: :e, desc: 'Add installed extensions', default: true
91
- def config(directory = '.')
92
- matches = []
93
- if options[:extensions]
94
- Gem::Specification.each do |g|
95
- puts g.name
96
- if g.name.match(/^solargraph\-[A-Za-z0-9_\-]*?\-ext/)
97
- require g.name
98
- matches.push g.name
99
- end
100
- end
101
- end
102
- conf = Solargraph::Workspace::Config.new.raw_data
103
- unless matches.empty?
104
- matches.each do |m|
105
- conf['extensions'].push m
106
- end
107
- end
108
- File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
109
- file.puts conf.to_yaml
110
- end
111
- STDOUT.puts "Configuration file initialized."
112
- end
113
-
114
- desc 'download-core [VERSION]', 'Download core documentation'
115
- def download_core version = nil
116
- ver = version || Solargraph::YardMap::CoreDocs.best_download
117
- puts "Downloading docs for #{ver}..."
118
- Solargraph::YardMap::CoreDocs.download ver
119
- end
120
-
121
- desc 'list-cores', 'List the local documentation versions'
122
- def list_cores
123
- puts Solargraph::YardMap::CoreDocs.versions.join("\n")
124
- end
125
-
126
- desc 'available-cores', 'List available documentation versions'
127
- def available_cores
128
- puts Solargraph::YardMap::CoreDocs.available.join("\n")
129
- end
130
-
131
- desc 'clear-cores', 'Clear the cached core documentation'
132
- def clear_cores
133
- Solargraph::YardMap::CoreDocs.clear
134
- end
135
- end
136
- end
1
+ require 'thor'
2
+ require 'json'
3
+ require 'fileutils'
4
+ require 'rubygems/package'
5
+ require 'zlib'
6
+ require 'eventmachine'
7
+
8
+ module Solargraph
9
+ class Shell < Thor
10
+ include Solargraph::ServerMethods
11
+
12
+ map %w[--version -v] => :version
13
+
14
+ desc "--version, -v", "Print the version"
15
+ def version
16
+ puts Solargraph::VERSION
17
+ end
18
+
19
+ desc 'server', 'Start a Solargraph server'
20
+ option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7657
21
+ option :views, type: :string, aliases: :v, desc: 'The view template directory', default: nil
22
+ option :files, type: :string, aliases: :f, desc: 'The public files directory', default: nil
23
+ def server
24
+ port = options[:port]
25
+ port = available_port if port.zero?
26
+ Solargraph::Server.set :port, port
27
+ Solargraph::Server.set :views, options[:views] unless options[:views].nil?
28
+ Solargraph::Server.set :public_folder, options[:files] unless options[:files].nil?
29
+ my_pid = nil
30
+ Solargraph::Server.run! do
31
+ # This line should not be necessary with WEBrick
32
+ #STDERR.puts "Solargraph server pid=#{Process.pid} port=#{port}"
33
+ my_pid = Process.pid
34
+ Signal.trap("INT") do
35
+ Solargraph::Server.stop!
36
+ end
37
+ Signal.trap("TERM") do
38
+ Solargraph::Server.stop!
39
+ end
40
+ end
41
+ end
42
+
43
+ desc 'socket', 'Run a Solargraph socket server'
44
+ option :host, type: :string, aliases: :h, desc: 'The server host', default: '127.0.0.1'
45
+ option :port, type: :numeric, aliases: :p, desc: 'The server port', default: 7658
46
+ def socket
47
+ port = options[:port]
48
+ port = available_port if port.zero?
49
+ EventMachine.run do
50
+ Signal.trap("INT") do
51
+ EventMachine.stop
52
+ end
53
+ Signal.trap("TERM") do
54
+ EventMachine.stop
55
+ end
56
+ EventMachine.start_server options[:host], port, Solargraph::LanguageServer::Transport::Socket
57
+ STDERR.puts "Solargraph is listening PORT=#{port} PID=#{Process.pid}"
58
+ end
59
+ end
60
+
61
+ desc 'suggest', 'Get code suggestions for the provided input'
62
+ long_desc <<-LONGDESC
63
+ Analyze a Ruby file and output a list of code suggestions in JSON format.
64
+ LONGDESC
65
+ option :line, type: :numeric, aliases: :l, desc: 'Zero-based line number', required: true
66
+ option :column, type: :numeric, aliases: [:c, :col], desc: 'Zero-based column number', required: true
67
+ option :filename, type: :string, aliases: :f, desc: 'File name', required: false
68
+ def suggest(*filenames)
69
+ STDERR.puts "WARNING: The `solargraph suggest` command is a candidate for deprecation. It will either change drastically or not exist in a future version."
70
+ # HACK: The ARGV array needs to be manipulated for ARGF.read to work
71
+ ARGV.clear
72
+ ARGV.concat filenames
73
+ text = ARGF.read
74
+ filename = options[:filename] || filenames[0]
75
+ begin
76
+ code_map = CodeMap.new(code: text, filename: filename)
77
+ offset = code_map.get_offset(options[:line], options[:column])
78
+ sugg = code_map.suggest_at(offset, filtered: true)
79
+ result = { "status" => "ok", "suggestions" => sugg }.to_json
80
+ STDOUT.puts result
81
+ rescue Exception => e
82
+ STDERR.puts e
83
+ STDERR.puts e.backtrace.join("\n")
84
+ result = { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
85
+ STDOUT.puts result
86
+ end
87
+ end
88
+
89
+ desc 'config [DIRECTORY]', 'Create or overwrite a default configuration file'
90
+ option :extensions, type: :boolean, aliases: :e, desc: 'Add installed extensions', default: true
91
+ def config(directory = '.')
92
+ matches = []
93
+ if options[:extensions]
94
+ Gem::Specification.each do |g|
95
+ puts g.name
96
+ if g.name.match(/^solargraph\-[A-Za-z0-9_\-]*?\-ext/)
97
+ require g.name
98
+ matches.push g.name
99
+ end
100
+ end
101
+ end
102
+ conf = Solargraph::Workspace::Config.new.raw_data
103
+ unless matches.empty?
104
+ matches.each do |m|
105
+ conf['extensions'].push m
106
+ end
107
+ end
108
+ File.open(File.join(directory, '.solargraph.yml'), 'w') do |file|
109
+ file.puts conf.to_yaml
110
+ end
111
+ STDOUT.puts "Configuration file initialized."
112
+ end
113
+
114
+ desc 'download-core [VERSION]', 'Download core documentation'
115
+ def download_core version = nil
116
+ ver = version || Solargraph::YardMap::CoreDocs.best_download
117
+ puts "Downloading docs for #{ver}..."
118
+ Solargraph::YardMap::CoreDocs.download ver
119
+ end
120
+
121
+ desc 'list-cores', 'List the local documentation versions'
122
+ def list_cores
123
+ puts Solargraph::YardMap::CoreDocs.versions.join("\n")
124
+ end
125
+
126
+ desc 'available-cores', 'List available documentation versions'
127
+ def available_cores
128
+ puts Solargraph::YardMap::CoreDocs.available.join("\n")
129
+ end
130
+
131
+ desc 'clear-cores', 'Clear the cached core documentation'
132
+ def clear_cores
133
+ Solargraph::YardMap::CoreDocs.clear
134
+ end
135
+ end
136
+ end