solargraph 0.15.4 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24b597ba06561ddd1bc1a8b4552b7d3bb1ee3867
4
- data.tar.gz: 37bc48eabc24b26b736b64f451402faa0cce7624
3
+ metadata.gz: b84e595d8f1d4042f81bbfb7c27dc56913a0de8c
4
+ data.tar.gz: 0ddfb700d7f1a8e10ec74f021954e1b9fa1375ce
5
5
  SHA512:
6
- metadata.gz: 9bdf2c98784584111834a166a87daab38c94aa9158db3efd05e655651b5b050afdcf488a7d33b78704f9cb04274a137ca047855df93dd1e91a9b010ce69b0b4a
7
- data.tar.gz: e7de68f3751c3a86cd7ed7c3ea3003a902ad72cf6fab8cac6f05a13190118b360e0da4926c707ffdaf5a7075a54a23c12e5e6b665d82279653cb3d5335020c80
6
+ metadata.gz: 171c19a787d30924b510b21d08c443c348d96d8c551fbefd03535dacc8e22fd289ace4f4f270e9469d61d813dc3c640e7ffed21d093826ef787173d0c80e5703
7
+ data.tar.gz: 88637fc48b37ef6bc2c7e3e5f4051fc87fa8901c829bf94bffc877d884f7e47fca750182241cb3d2cf539811e7c9275358a0792a42e6ea666815b59bb94a24c8
@@ -34,16 +34,18 @@ module Solargraph
34
34
 
35
35
  # @param workspace [String]
36
36
  def initialize workspace = nil
37
+ @@source_cache.clear
37
38
  @workspace = workspace.gsub(/\\/, '/') unless workspace.nil?
38
39
  clear
39
40
  require_extensions
40
41
  unless @workspace.nil?
41
- workspace_files.concat (self.config.included - self.config.excluded)
42
+ workspace_files.concat config.calculated
42
43
  workspace_files.each do |wf|
43
44
  begin
44
45
  @@source_cache[wf] ||= Source.load(wf)
45
46
  rescue Parser::SyntaxError => e
46
47
  STDERR.puts "Failed to load #{wf}: #{e.message}"
48
+ @@source_cache[wf] = Source.virtual('', wf)
47
49
  end
48
50
  end
49
51
  end
@@ -132,6 +134,21 @@ module Solargraph
132
134
  process_maps if @stale or force
133
135
  end
134
136
 
137
+ def changed?
138
+ current = config.calculated
139
+ unless (Set.new(current) ^ workspace_files).empty?
140
+ STDERR.puts "Change based on difference in file list"
141
+ return true
142
+ end
143
+ current.each do |f|
144
+ if !File.exist?(f) or File.mtime(f) != source_file_mtime(f)
145
+ STDERR.puts "Change based on file #{f}"
146
+ return true
147
+ end
148
+ end
149
+ false
150
+ end
151
+
135
152
  # Get the docstring associated with a node.
136
153
  #
137
154
  # @param node [AST::Node]
@@ -468,9 +485,9 @@ module Solargraph
468
485
  end
469
486
  end
470
487
  strings = meths.map(&:to_s)
471
- live_map.get_methods(fqns, '', 'class', visibility.include?(:private)).each do |m|
472
- next if strings.include?(m) or !m.match(/^[a-z]/i)
473
- meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}.#{m}")
488
+ live_map.get_methods(fqns, '', 'class', visibility.include?(:private)).each do |ls|
489
+ next if strings.include?(ls.to_s)
490
+ meths.push ls
474
491
  end
475
492
  meths
476
493
  end
@@ -507,9 +524,9 @@ module Solargraph
507
524
  end
508
525
  end
509
526
  strings = meths.map(&:to_s)
510
- live_map.get_methods(namespace, root, 'instance', visibility.include?(:private)).each do |m|
511
- next if strings.include?(m) or !m.match(/^[a-z]/i)
512
- meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}##{m}")
527
+ live_map.get_methods(fqns, '', 'class', visibility.include?(:private)).each do |ls|
528
+ next if strings.include?(ls.to_s)
529
+ meths.push ls
513
530
  end
514
531
  meths
515
532
  end
@@ -539,6 +556,8 @@ module Solargraph
539
556
  if @workspace_files.include?(filename)
540
557
  eliminate filename
541
558
  @@source_cache[filename] = Source.load(filename)
559
+ @sources.delete filename
560
+ @sources[filename] = @@source_cache[filename]
542
561
  rebuild_local_yardoc #if @workspace_files.include?(filename)
543
562
  @stale = true
544
563
  else
@@ -845,6 +864,7 @@ module Solargraph
845
864
  if scope == :class and part == 'new'
846
865
  scope = :instance
847
866
  elsif !METHODS_RETURNING_SELF.include?(part)
867
+ type = nil
848
868
  visibility = [:public]
849
869
  visibility.concat [:private, :protected] if top
850
870
  if scope == :instance || namespace == ''
@@ -860,7 +880,7 @@ module Solargraph
860
880
  end
861
881
  top = false
862
882
  end
863
- if scope == :class
883
+ if scope == :class and !type.nil?
864
884
  type = "Class<#{type}>"
865
885
  end
866
886
  type
@@ -957,5 +977,13 @@ module Solargraph
957
977
  end
958
978
  result
959
979
  end
980
+
981
+ def source_file_mtime(filename)
982
+ # @todo This is naively inefficient.
983
+ sources.each do |s|
984
+ return s.mtime if s.filename == filename
985
+ end
986
+ nil
987
+ end
960
988
  end
961
989
  end
@@ -40,7 +40,8 @@ module Solargraph
40
40
  # @return [Array<String>]
41
41
  def included
42
42
  return [] if workspace.nil?
43
- @included ||= process_globs(@raw_data['include'])
43
+ #@included ||= process_globs(@raw_data['include'])
44
+ process_globs(@raw_data['include'])
44
45
  end
45
46
 
46
47
  # An array of files excluded from the workspace.
@@ -48,14 +49,16 @@ module Solargraph
48
49
  # @return [Array<String>]
49
50
  def excluded
50
51
  return [] if workspace.nil?
51
- @excluded ||= process_globs(@raw_data['exclude'])
52
+ #@excluded ||= process_globs(@raw_data['exclude'])
53
+ process_globs(@raw_data['exclude'])
52
54
  end
53
55
 
54
56
  # The calculated array of (included - excluded) files in the workspace.
55
57
  #
56
58
  # @return [Array<String>]
57
59
  def calculated
58
- @calculated ||= (included - excluded)
60
+ #@calculated ||= (included - excluded)
61
+ included - excluded
59
62
  end
60
63
 
61
64
  # @return [Array<String>]
@@ -77,7 +80,7 @@ module Solargraph
77
80
  result = []
78
81
  globs.each do |glob|
79
82
  Dir[File.join workspace, glob].each do |f|
80
- result.push File.realdirpath(f)
83
+ result.push File.realdirpath(f).gsub(/\\/, '/')
81
84
  end
82
85
  end
83
86
  result
@@ -15,6 +15,8 @@ module Solargraph
15
15
  # @return [String]
16
16
  attr_reader :filename
17
17
 
18
+ attr_reader :mtime
19
+
18
20
  # @return [Array<Integer>]
19
21
  attr_reader :stubbed_lines
20
22
 
@@ -29,6 +31,7 @@ module Solargraph
29
31
  @directives = {}
30
32
  @docstring_hash = associate_comments(node, comments)
31
33
  @filename = filename
34
+ @mtime = (!filename.nil? and File.exist?(filename) ? File.mtime(filename) : nil)
32
35
  @namespace_nodes = {}
33
36
  @all_nodes = []
34
37
  @node_stack = []
@@ -391,6 +394,11 @@ module Solargraph
391
394
  stubs = []
392
395
  fixed_position = false
393
396
  tmp = code
397
+ if !offset.nil? and offset > 0
398
+ if tmp[offset - 1] == '.'
399
+ tmp = tmp[0..offset-2] + '_' + tmp[offset..-1]
400
+ end
401
+ end
394
402
  begin
395
403
  node, comments = Parser::CurrentRuby.parse_with_comments(tmp)
396
404
  Source.new(code, node, comments, filename, stubs)
@@ -25,6 +25,10 @@ module Solargraph
25
25
 
26
26
  include NodeMethods
27
27
 
28
+ METHODS_WITH_YIELDPARAM_SUBTYPES = %w[
29
+ Array#each Hash#each_pair Array#map
30
+ ]
31
+
28
32
  def initialize code: '', filename: nil, api_map: nil, cursor: nil
29
33
  # HACK: Adjust incoming filename's path separator for yardoc file comparisons
30
34
  filename = filename.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless filename.nil? or File::ALT_SEPARATOR.nil?
@@ -346,7 +350,11 @@ module Solargraph
346
350
  yp = get_yieldparams_at(index).keep_if{|s| s.to_s == parts[0]}.first
347
351
  unless yp.nil?
348
352
  if parts[1].nil? or parts[1].empty?
349
- result = yp.return_type
353
+ if yp.return_type.nil?
354
+ STDERR.puts "Here is where we try to get the stupid, you know, the yieldparam type"
355
+ else
356
+ result = yp.return_type
357
+ end
350
358
  else
351
359
  newsig = parts[1..-1].join('.')
352
360
  result = api_map.infer_signature_type(newsig, yp.return_type, scope: :instance)
@@ -405,7 +413,7 @@ module Solargraph
405
413
  end
406
414
  unless signature.include?('.')
407
415
  fqns = api_map.find_fully_qualified_namespace(signature, ns_here)
408
- return "Class<#{fqns}>" unless fqns.nil?
416
+ return "Class<#{fqns}>" unless fqns.nil? or fqns.empty?
409
417
  end
410
418
  start = parts[0]
411
419
  return nil if start.nil?
@@ -626,7 +634,16 @@ module Solargraph
626
634
  end
627
635
  i = 0
628
636
  block_node.children[1].children.each do |a|
629
- rt = (yps[i].nil? ? nil : yps[i].types[0])
637
+ rt = nil
638
+ if yps[i].nil? or yps[i].types.nil? or yps[i].types.empty?
639
+ zsig = api_map.resolve_node_signature(block_node.children[0])
640
+ vartype = infer_signature_from_node(zsig.split('.').first, scope_node)
641
+ subtypes = get_subtypes(vartype)
642
+ zpath = infer_path_from_signature_and_node(zsig, scope_node)
643
+ rt = subtypes[i] if METHODS_WITH_YIELDPARAM_SUBTYPES.include?(zpath)
644
+ else
645
+ rt = yps[i].types[0]
646
+ end
630
647
  result.push Suggestion.new(a.children[0], kind: Suggestion::PROPERTY, return_type: rt)
631
648
  i += 1
632
649
  end
@@ -777,5 +794,19 @@ module Solargraph
777
794
  cursor = nil if cursor < 0
778
795
  cursor
779
796
  end
797
+
798
+ def infer_path_from_signature_and_node signature, node
799
+ # @todo Improve this method
800
+ parts = signature.split('.')
801
+ last = parts.pop
802
+ type = infer_signature_from_node(parts.join('.'), node)
803
+ "#{type.gsub(/<[a-z0-9:, ]*>/i, '')}##{last}"
804
+ end
805
+
806
+ def get_subtypes type
807
+ match = type.match(/<([a-z0-9_:, ]*)>/i)
808
+ return [] if match.nil?
809
+ match[1].split(',').map(&:strip)
810
+ end
780
811
  end
781
812
  end
@@ -15,6 +15,7 @@ module Solargraph
15
15
  end
16
16
 
17
17
  def get_methods(namespace, root = '', scope = 'instance', with_private = false)
18
+ fqns = api_map.find_fully_qualified_namespace(namespace, root)
18
19
  params = {
19
20
  namespace: namespace, root: root, scope: scope, with_private: with_private
20
21
  }
@@ -24,7 +25,9 @@ module Solargraph
24
25
  result = []
25
26
  runners.each do |p|
26
27
  next if did_runtime and p.runtime?
27
- result.concat p.get_methods(namespace: namespace, root: root, scope: scope, with_private: with_private)
28
+ p.get_methods(namespace: namespace, root: root, scope: scope, with_private: with_private).each do |m|
29
+ result.push Suggestion.new(m['name'], kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}.#{m['name']}", arguments: m['parameters'])
30
+ end
28
31
  did_runtime = true if p.runtime?
29
32
  end
30
33
  cache.set_methods(params, result)
@@ -71,7 +71,14 @@ module Solargraph
71
71
  result.concat con.public_instance_methods(false)
72
72
  end
73
73
  end
74
- respond_ok result.uniq
74
+ respond_ok (result.uniq.sort.map do |name|
75
+ # @type [Method]
76
+ meth = con.method(name)
77
+ {
78
+ name: name,
79
+ parameters: build_parameter_array(meth.parameters)
80
+ }
81
+ end)
75
82
  end
76
83
 
77
84
  def get_constants args
@@ -138,6 +145,26 @@ module Solargraph
138
145
  data: []
139
146
  }.to_json
140
147
  end
148
+
149
+ def build_parameter_array parameters
150
+ an = 1
151
+ parameters.map do |p|
152
+ if p[0] == :rest
153
+ str = (p[1] ? "*#{p[1]}" : "*args")
154
+ else
155
+ str = (p[1] ? p[1].to_s : "arg#{an}")
156
+ if p[0] == :opt
157
+ str += ' = ?'
158
+ elsif p[0] == :key
159
+ str += ':'
160
+ elsif p[0] == :keyreq
161
+ str += ': ?'
162
+ end
163
+ end
164
+ an += 1
165
+ str
166
+ end
167
+ end
141
168
  end
142
169
  end
143
170
  end
@@ -172,6 +172,30 @@ module Solargraph
172
172
  end
173
173
  end
174
174
 
175
+ def run!
176
+ Thread.new do
177
+ while true
178
+ watch_workspaces
179
+ sleep 1
180
+ end
181
+ end
182
+ super
183
+ end
184
+
185
+ def watch_workspaces
186
+ @@semaphore.synchronize do
187
+ changed = {}
188
+ @@api_hash.each_pair do |w, a|
189
+ next unless a.changed?
190
+ STDERR.puts "Reloading changed workspace #{w}"
191
+ n = Solargraph::ApiMap.new(w)
192
+ changed[w] = n
193
+ end
194
+ changed.each_pair do |w, a|
195
+ @@api_hash[w] = a
196
+ end
197
+ end
198
+ end
175
199
  end
176
200
 
177
201
  class Helpers
@@ -21,8 +21,7 @@ module Solargraph
21
21
  option :files, type: :string, aliases: :f, desc: 'The public files directory', default: nil
22
22
  def server
23
23
  port = options[:port]
24
- # This line should not be necessary with WEBrick
25
- #port = available_port if port.zero?
24
+ port = available_port if port.zero?
26
25
  Solargraph::Server.set :port, port
27
26
  Solargraph::Server.set :views, options[:views] unless options[:views].nil?
28
27
  Solargraph::Server.set :public_folder, options[:files] unless options[:files].nil?
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.15.4'
2
+ VERSION = '0.16.0'
3
3
  end
@@ -225,7 +225,7 @@ module Solargraph
225
225
  end
226
226
 
227
227
  def find_fully_qualified_namespace namespace, scope
228
- unless scope.empty?
228
+ unless scope.nil? or scope.empty?
229
229
  parts = scope.split('::')
230
230
  while parts.length > 0
231
231
  here = "#{parts.join('::')}::#{namespace}"
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.15.4
4
+ version: 0.16.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: 2018-01-02 00:00:00.000000000 Z
11
+ date: 2018-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser