solargraph 0.13.3 → 0.14.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.
@@ -0,0 +1,25 @@
1
+ module Solargraph
2
+ module Pin
3
+ module Plugin
4
+ class Method < Base
5
+ attr_reader :name
6
+ attr_reader :path
7
+ attr_reader :return_type
8
+ attr_reader :parameters
9
+ attr_reader :scope
10
+ attr_reader :visibility
11
+
12
+ def initialize name:, path:, return_type:, parameters:
13
+ @name = name
14
+ @path = path
15
+ @return_type = return_type
16
+ @parameters = parameters
17
+ end
18
+
19
+ def kind
20
+ Solargraph::Suggestion::METHOD
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,37 +1,40 @@
1
1
  module Solargraph
2
2
  module Plugin
3
3
  class Base
4
+ # @return [Solargraph::ApiMap]
5
+ attr_reader :api_map
4
6
 
5
- def initialize workspace
6
- # @!attribute [r] workspace
7
- # @return [String]
8
- define_singleton_method(:workspace) { workspace }
7
+ def initialize api_map
8
+ @api_map = api_map
9
9
  post_initialize
10
10
  end
11
11
 
12
12
  def post_initialize
13
13
  end
14
14
 
15
- def start
16
- raise "#{self.class} needs to implement the start method"
15
+ # @return [Array<String>]
16
+ def get_methods namespace:, root:, scope:, with_private: false
17
+ []
17
18
  end
18
19
 
19
- def stop
20
- raise "#{self.class} needs to implement the stop method"
20
+ # @return [Array<String>]
21
+ def get_constants namespace, root
22
+ []
21
23
  end
22
24
 
23
- def get_methods namespace:, root:, scope:, with_private: false
24
- raise "#{self.class} needs to implement the get_methods method"
25
+ # @return [String]
26
+ def get_fqns namespace, root
27
+ nil
25
28
  end
26
29
 
27
- protected
28
-
29
- def respond_ok data
30
- Solargraph::Plugin::Response.new('ok', data)
30
+ # @return [Boolean]
31
+ def refresh
32
+ false
31
33
  end
32
34
 
33
- def respond_err exception
34
- Solargraph::Plugin::Response.new('err', [], exception.message)
35
+ # @return [Boolean]
36
+ def runtime?
37
+ false
35
38
  end
36
39
  end
37
40
  end
@@ -0,0 +1,11 @@
1
+ module Solargraph
2
+ module Plugin
3
+ # A placeholder plugin for disabling the default Runtime plugin.
4
+ #
5
+ class Canceler < Base
6
+ def runtime?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,145 @@
1
+ require 'json'
2
+
3
+ module Solargraph
4
+ module Plugin
5
+ class Process
6
+ def initialize
7
+ @required = []
8
+ post_initialize
9
+ end
10
+
11
+ def post_initialize
12
+ end
13
+
14
+ def run
15
+ until STDIN.closed?
16
+ input = gets
17
+ break if input.nil?
18
+ args = nil
19
+ begin
20
+ args = JSON.parse(input)
21
+ case args['command']
22
+ when 'require'
23
+ STDOUT.puts do_require args['paths']
24
+ when 'methods'
25
+ STDOUT.puts get_methods args['params']
26
+ when 'constants'
27
+ STDOUT.puts get_constants args['params']
28
+ when 'fqns'
29
+ STDOUT.puts get_fqns args['params']
30
+ else
31
+ STDOUT.puts respond_err "Unrecognized command #{args['command']}"
32
+ end
33
+ rescue JSON::ParserError => e
34
+ STDOUT.puts respond_err "Error parsing input: #{e.message}"
35
+ end
36
+ STDOUT.flush
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def do_require paths
43
+ errors = []
44
+ paths.each do |p|
45
+ begin
46
+ require p
47
+ @required.push p
48
+ rescue Exception => e
49
+ STDERR.puts "Failed to require #{p}: #{e.message}"
50
+ errors.push "Failed to require #{p}: #{e.class} #{e.message}"
51
+ end
52
+ end
53
+ if errors.empty?
54
+ respond_ok
55
+ else
56
+ respond_err errors.join('; ')
57
+ end
58
+ end
59
+
60
+ def get_methods args
61
+ result = []
62
+ con = find_constant(args['namespace'], args['root'])
63
+ unless con.nil?
64
+ if (args['scope'] == 'class')
65
+ if args['with_private']
66
+ result.concat con.methods
67
+ else
68
+ result.concat con.public_methods
69
+ end
70
+ elsif (args['scope'] == 'instance')
71
+ if args['with_private']
72
+ result.concat con.instance_methods
73
+ else
74
+ result.concat con.public_instance_methods
75
+ end
76
+ end
77
+ end
78
+ respond_ok result
79
+ end
80
+
81
+ def get_constants args
82
+ result = []
83
+ con = find_constant(args['namespace'], args['root'])
84
+ unless con.nil?
85
+ #result.concat con.constants
86
+ con.constants.each do |c|
87
+ next if c == :Solargraph and !@required.include?('solargraph')
88
+ item = { name: c }
89
+ here = con.const_get(c)
90
+ item[:class] = here.class.to_s
91
+ result.push item
92
+ end
93
+ end
94
+ respond_ok result
95
+ end
96
+
97
+ def get_fqns args
98
+ con = find_constant(args['namespace'], args['root'])
99
+ respond_ok (con.nil? ? nil : con.to_s)
100
+ end
101
+
102
+ def find_constant(namespace, root)
103
+ result = nil
104
+ parts = root.split('::')
105
+ until parts.empty?
106
+ result = inner_find_constant("#{parts.join('::')}::#{namespace}")
107
+ parts.pop
108
+ break unless result.nil?
109
+ end
110
+ result = inner_find_constant(namespace) if result.nil?
111
+ result
112
+ end
113
+
114
+ def inner_find_constant(namespace)
115
+ cursor = Object
116
+ parts = namespace.split('::')
117
+ until parts.empty?
118
+ here = parts.shift
119
+ begin
120
+ cursor = cursor.const_get(here)
121
+ rescue NameError
122
+ return nil
123
+ end
124
+ end
125
+ cursor
126
+ end
127
+
128
+ def respond_ok data = []
129
+ {
130
+ status: 'ok',
131
+ message: nil,
132
+ data: data
133
+ }.to_json
134
+ end
135
+
136
+ def respond_err msg
137
+ {
138
+ status: 'err',
139
+ message: msg,
140
+ data: []
141
+ }.to_json
142
+ end
143
+ end
144
+ end
145
+ end
@@ -1,14 +1,130 @@
1
+ require 'json'
2
+
1
3
  module Solargraph
2
4
  module Plugin
3
5
  class Runtime < Base
4
- def start
6
+ attr_writer :executable
7
+
8
+ def executable
9
+ @executable ||= 'solargraph-runtime'
10
+ end
11
+
12
+ def post_initialize
13
+ start_process
5
14
  end
6
15
 
7
- def stop
16
+ # @return [Boolean]
17
+ def runtime?
18
+ true
8
19
  end
9
20
 
21
+ # Get an array of method names.
22
+ #
23
+ # @return [Array<String>]
10
24
  def get_methods namespace:, root:, scope:, with_private: false
11
- raise "#{self.class} needs to implement the get_methods method"
25
+ response = send_get_methods(namespace, root, scope, with_private)
26
+ response['data']
27
+ end
28
+
29
+ # Get an array of constant names.
30
+ #
31
+ # @return [Array<String>]
32
+ def get_constants namespace, root
33
+ response = send_get_constants namespace, root
34
+ response['data']
35
+ end
36
+
37
+ def get_fqns namespace, root
38
+ response = send_get_fqns namespace, root
39
+ response['data']
40
+ end
41
+
42
+ def refresh
43
+ if api_map.nil?
44
+ false
45
+ else
46
+ if @current_required != api_map.required
47
+ STDERR.puts "Restarting #{self.class} process"
48
+ @io.close unless @io.nil? or @io.closed?
49
+ start_process
50
+ true
51
+ else
52
+ false
53
+ end
54
+ end
55
+ end
56
+
57
+ protected
58
+
59
+ def load_environment
60
+ return if api_map.nil?
61
+ STDERR.puts "Required paths given to Runtime: #{api_map.required}"
62
+ send_require api_map.required
63
+ @current_required = api_map.required.clone
64
+ end
65
+
66
+ private
67
+
68
+ def start_process
69
+ dir = Dir.pwd
70
+ unless api_map.nil? or api_map.workspace.nil?
71
+ dir = api_map.workspace
72
+ end
73
+ STDERR.puts "Starting #{self.class} process in #{dir}"
74
+ Dir.chdir(dir) do
75
+ @io = IO.popen(executable, 'r+')
76
+ end
77
+ load_environment
78
+ end
79
+
80
+ def send_require paths
81
+ cmd = {
82
+ command: 'require',
83
+ paths: paths
84
+ }
85
+ transact cmd
86
+ end
87
+
88
+ def send_get_methods namespace, root, scope, with_private
89
+ cmd = {
90
+ command: 'methods',
91
+ params: {
92
+ namespace: namespace,
93
+ root: root,
94
+ scope: scope,
95
+ with_private: with_private
96
+ }
97
+ }
98
+ transact cmd
99
+ end
100
+
101
+ def send_get_constants namespace, root
102
+ cmd = {
103
+ command: 'constants',
104
+ params: {
105
+ namespace: namespace,
106
+ root: root
107
+ }
108
+ }
109
+ transact cmd
110
+ end
111
+
112
+ def send_get_fqns namespace, root
113
+ cmd = {
114
+ command: 'fqns',
115
+ params: {
116
+ namespace: namespace,
117
+ root: root
118
+ }
119
+ }
120
+ transact cmd
121
+ end
122
+
123
+ def transact cmd
124
+ @io.puts cmd.to_json
125
+ @io.flush
126
+ result = @io.gets
127
+ JSON.parse(result)
12
128
  end
13
129
  end
14
130
  end
@@ -2,6 +2,7 @@ module Solargraph
2
2
  module Plugin
3
3
  autoload :Base, 'solargraph/plugin/base'
4
4
  autoload :Runtime, 'solargraph/plugin/runtime'
5
- autoload :Response, 'solargraph/plugin/response'
5
+ autoload :Canceler, 'solargraph/plugin/canceler'
6
+ autoload :Process, 'solargraph/plugin/process'
6
7
  end
7
8
  end
@@ -47,10 +47,11 @@ module Solargraph
47
47
  @@semaphore.synchronize {
48
48
  api_map = @@api_hash[workspace]
49
49
  }
50
+ with_all = params['all'] == '1' ? true : false
50
51
  code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: api_map, cursor: [params['line'].to_i, params['column'].to_i])
51
52
  offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
52
53
  sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false, filtered: true)
53
- JSON.generate({ "status" => "ok", "suggestions" => sugg.map(&:as_json) })
54
+ JSON.generate({ "status" => "ok", "suggestions" => sugg.map{|s| s.as_json(all: with_all)} })
54
55
  rescue Exception => e
55
56
  STDERR.puts e
56
57
  STDERR.puts e.backtrace.join("\n")
@@ -76,6 +77,20 @@ module Solargraph
76
77
  end
77
78
  end
78
79
 
80
+ post '/resolve' do
81
+ content_type :json
82
+ workspace = params['workspace'] || nil
83
+ result = []
84
+ @@semaphore.synchronize {
85
+ api_map = @@api_hash[workspace]
86
+ unless api_map.nil?
87
+ # @todo Get suggestions that match the path
88
+ result.concat api_map.get_path_suggestions(params['path'])
89
+ end
90
+ }
91
+ { "status" => "ok", "suggestions" => result.map{|s| s.as_json(all: true)} }.to_json
92
+ end
93
+
79
94
  post '/hover' do
80
95
  content_type :json
81
96
  begin
@@ -118,6 +133,10 @@ module Solargraph
118
133
  erb :document
119
134
  end
120
135
 
136
+ post '/shutdown' do
137
+ exit
138
+ end
139
+
121
140
  def htmlify text
122
141
  rdoc_to_html text
123
142
  end
@@ -133,10 +152,6 @@ module Solargraph
133
152
  end
134
153
 
135
154
  class << self
136
- #def run!
137
- # super
138
- #end
139
-
140
155
  def prepare_workspace directory
141
156
  Thread.new do
142
157
  @@semaphore.synchronize do
@@ -146,6 +161,7 @@ module Solargraph
146
161
  end
147
162
  end
148
163
  end
164
+
149
165
  end
150
166
 
151
167
  class Helpers
@@ -1,3 +1,5 @@
1
+ require 'socket'
2
+
1
3
  module Solargraph
2
4
  module ServerMethods
3
5
  def available_port
@@ -3,9 +3,6 @@ require 'json'
3
3
  require 'fileutils'
4
4
  require 'rubygems/package'
5
5
  require 'zlib'
6
- require 'net/http'
7
- require 'socket'
8
- require 'bundler'
9
6
 
10
7
  module Solargraph
11
8
  class Shell < Thor
@@ -63,11 +60,31 @@ module Solargraph
63
60
  Solargraph::Server.set :port, port
64
61
  Solargraph::Server.set :views, options[:views] unless options[:views].nil?
65
62
  Solargraph::Server.set :public_folder, options[:files] unless options[:files].nil?
63
+ my_pid = nil
66
64
  Solargraph::Server.run! do
67
65
  STDERR.puts "Solargraph server pid=#{Process.pid} port=#{port}"
66
+ my_pid = Process.pid
67
+ Signal.trap("INT") do
68
+ Solargraph::Server.stop!
69
+ end
70
+ Signal.trap("TERM") do
71
+ Solargraph::Server.stop!
72
+ end
68
73
  end
69
74
  end
70
75
 
76
+
77
+ desc 'plugin PLUGIN_NAME', 'Run a Solargraph runtime plugin'
78
+ option :workspace, type: :string, aliases: :w, desc: 'The workspace'
79
+ option :port, type: :numeric, aliases: :p, desc: 'The server port', required: true
80
+ option :ppid, type: :numeric, desc: 'ppid'
81
+ def plugin plugin_name
82
+ # @todo Find the correct plugin based on the provided name
83
+ cls = Solargraph::Plugin::Runtime
84
+ #SolargraphRailsExt::Server.new(options[:workspace], options[:port]).run
85
+ cls.serve options[:workspace], options[:port], options[:ppid]
86
+ end
87
+
71
88
  desc 'suggest', 'Get code suggestions for the provided input'
72
89
  long_desc <<-LONGDESC
73
90
  Analyze a Ruby file and output a list of code suggestions in JSON format.
@@ -96,8 +96,11 @@ module Solargraph
96
96
  @params
97
97
  end
98
98
 
99
+ def inject_detail
100
+ end
101
+
99
102
  def as_json args = {}
100
- {
103
+ result = {
101
104
  label: @label,
102
105
  kind: @kind,
103
106
  insert: @insert,
@@ -106,17 +109,19 @@ module Solargraph
106
109
  location: (@location.nil? ? nil : @location.to_s),
107
110
  arguments: @arguments,
108
111
  params: params,
109
- return_type: return_type,
110
- documentation: documentation
112
+ return_type: return_type
111
113
  }
114
+ result[:documentation] = documentation if args[:all]
115
+ result
112
116
  end
113
117
 
114
118
  def to_json args = {}
115
119
  as_json.to_json(args)
116
120
  end
117
121
 
122
+ # @param pin [Solargraph::Pin::Base]
118
123
  def self.pull pin, return_type = nil
119
- Suggestion.new(pin.name, insert: pin.name.gsub(/=/, ' = '), kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path, return_type: return_type)
124
+ Suggestion.new(pin.name, insert: pin.name.gsub(/=/, ' = '), kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path, return_type: return_type, location: pin.location)
120
125
  end
121
126
  end
122
127
 
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.13.3'
2
+ VERSION = '0.14.0'
3
3
  end
@@ -2,8 +2,14 @@ require 'parser/current'
2
2
  require 'yard'
3
3
 
4
4
  module Solargraph
5
-
6
5
  class YardMap
6
+ @@stdlib_yardoc = File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc-stdlib')
7
+ @@stdlib_namespaces = []
8
+ YARD::Registry.load! @@stdlib_yardoc
9
+ YARD::Registry.all(:class, :module).each do |ns|
10
+ @@stdlib_namespaces.push ns.path
11
+ end
12
+
7
13
  autoload :Cache, 'solargraph/yard_map/cache'
8
14
 
9
15
  attr_reader :workspace
@@ -35,6 +41,7 @@ module Solargraph
35
41
  end
36
42
  end
37
43
  yardocs.push File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc')
44
+ #yardocs.push File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc-stdlib')
38
45
  yardocs.uniq!
39
46
  yardocs.each do |y|
40
47
  load_yardoc y
@@ -43,7 +50,7 @@ module Solargraph
43
50
  @namespace_yardocs[ns.path].push y
44
51
  end
45
52
  end
46
- #cache_core
53
+ cache_core
47
54
  end
48
55
 
49
56
  # @return [Solargraph::LiveMap]
@@ -73,7 +80,7 @@ module Solargraph
73
80
  # @param query [String]
74
81
  def search query
75
82
  found = []
76
- yardocs.each { |y|
83
+ (yardocs + [@@stdlib_yardoc]).each { |y|
77
84
  yard = load_yardoc(y)
78
85
  unless yard.nil?
79
86
  yard.paths.each { |p|
@@ -87,7 +94,7 @@ module Solargraph
87
94
  # @param query [String]
88
95
  def document query
89
96
  found = []
90
- yardocs.each { |y|
97
+ (yardocs + [@@stdlib_yardoc]).each { |y|
91
98
  yard = load_yardoc(y)
92
99
  unless yard.nil?
93
100
  obj = yard.at query
@@ -256,6 +263,22 @@ module Solargraph
256
263
  result
257
264
  end
258
265
 
266
+ # @return [Symbol] :class, :module, or nil
267
+ def get_namespace_type(fqns)
268
+ yardocs_documenting(fqns).each do |y|
269
+ yard = load_yardoc y
270
+ unless yard.nil?
271
+ obj = yard.at(fqns)
272
+ unless obj.nil?
273
+ return :class if obj.kind_of?(YARD::CodeObjects::ClassObject)
274
+ return :module if obj.kind_of?(YARD::CodeObjects::ModuleObject)
275
+ return nil
276
+ end
277
+ end
278
+ end
279
+ nil
280
+ end
281
+
259
282
  def bundled_gem_yardocs
260
283
  result = []
261
284
  unless workspace.nil?
@@ -320,7 +343,7 @@ module Solargraph
320
343
  end
321
344
 
322
345
  def cache_core
323
- c = get_constants '', ''
346
+ get_constants '', ''
324
347
  end
325
348
 
326
349
  def kind_of_object obj
@@ -340,7 +363,7 @@ module Solargraph
340
363
  spec.nondevelopment_dependencies.each do |dep|
341
364
  gy = YARD::Registry.yardoc_file_for_gem(dep.name)
342
365
  if gy.nil?
343
- STDERR.puts "Required path not found: #{r}"
366
+ STDERR.puts "Required path not found: #{dep.name}"
344
367
  else
345
368
  #STDERR.puts "Adding #{gy}"
346
369
  yardocs.unshift gy
@@ -367,6 +390,7 @@ module Solargraph
367
390
  else
368
391
  result.concat @namespace_yardocs[namespace] unless @namespace_yardocs[namespace].nil?
369
392
  end
393
+ result.push @@stdlib_yardoc if result.empty? and @@stdlib_namespaces.include?(namespace)
370
394
  result
371
395
  end
372
396
  end
data/lib/solargraph.rb CHANGED
@@ -3,9 +3,7 @@ require 'rubygems/package'
3
3
  require 'yard-solargraph'
4
4
 
5
5
  module Solargraph
6
- autoload :Analyzer, 'solargraph/analyzer'
7
6
  autoload :Shell, 'solargraph/shell'
8
- autoload :LiveParser, 'solargraph/live_parser'
9
7
  autoload :ApiMap, 'solargraph/api_map'
10
8
  autoload :CodeMap, 'solargraph/code_map'
11
9
  autoload :NodeMethods, 'solargraph/node_methods'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-07 00:00:00.000000000 Z
11
+ date: 2017-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -180,10 +180,12 @@ description: IDE tools for code completion and inline documentation
180
180
  email: admin@castwide.com
181
181
  executables:
182
182
  - solargraph
183
+ - solargraph-runtime
183
184
  extensions: []
184
185
  extra_rdoc_files: []
185
186
  files:
186
187
  - bin/solargraph
188
+ - bin/solargraph-runtime
187
189
  - lib/solargraph.rb
188
190
  - lib/solargraph/api_map.rb
189
191
  - lib/solargraph/api_map/cache.rb
@@ -206,10 +208,12 @@ files:
206
208
  - lib/solargraph/pin/instance_variable.rb
207
209
  - lib/solargraph/pin/local_variable.rb
208
210
  - lib/solargraph/pin/method.rb
211
+ - lib/solargraph/pin/plugin/method.rb
209
212
  - lib/solargraph/pin/symbol.rb
210
213
  - lib/solargraph/plugin.rb
211
214
  - lib/solargraph/plugin/base.rb
212
- - lib/solargraph/plugin/response.rb
215
+ - lib/solargraph/plugin/canceler.rb
216
+ - lib/solargraph/plugin/process.rb
213
217
  - lib/solargraph/plugin/runtime.rb
214
218
  - lib/solargraph/server.rb
215
219
  - lib/solargraph/server_methods.rb