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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 613c6ae706229464a6f918aef5f093a97e0ff569
4
- data.tar.gz: b68e4d8abbf2b884d78f9af364e34e5cbcde6f2f
3
+ metadata.gz: 0d9090bbc3094234313c93d9cbc44461426c9fd8
4
+ data.tar.gz: 802563c75b5edb831701442e15bb0e7715934b8a
5
5
  SHA512:
6
- metadata.gz: 843ff75f0ccf680f311a3e42ba4e5ff18810ff1beb048638503c3e7b794883b1bd419c2dd2b6bb3d56bc17a3a06e8e5a7d392f9abf458c57affe0f219ae2ad7a
7
- data.tar.gz: a3b5f6d57c62b1d35e940e29b6c8e9b70594a73f1f6f37021a31cfee11eefc3495cb1d09f13de70b1722a9d42bfde9ce827682df898198c6dad5b59918c76419
6
+ metadata.gz: f6d2eedfd1dafc0c280643b6f21401f61c4dbb2e3cd89273a6cc9892d25528412e04701a2501d63708535d5f2024d7a7b3773185dd03877dd957f938237db7d5
7
+ data.tar.gz: 4dca225b820a8ac799475936649673cff8f9d20bb389f719568ee9098f85fb68cfef83d215cd8ab2a84225162d1b2619bfffc71417a810ecfb2ac0d7d1975e38
data/bin/solargraph CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift '/home/fred/solargraph-ruby/lib'
4
3
  require 'solargraph'
5
4
 
6
5
  Solargraph::Shell.start(ARGV)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'solargraph/plugin/process'
4
+
5
+ Solargraph::Plugin::Process.new.run
@@ -3,23 +3,44 @@ require 'yaml'
3
3
  module Solargraph
4
4
  class ApiMap
5
5
  class Config
6
+ # @return [String]
6
7
  attr_reader :workspace
7
8
  attr_reader :raw_data
8
9
 
10
+ # @return [Array<String>]
11
+ attr_reader :included
12
+
13
+ # @return [Array<String>]
14
+ attr_reader :excluded
15
+
16
+ # @return [Array<String>]
17
+ attr_reader :domains
18
+
9
19
  def initialize workspace = nil
10
20
  @workspace = workspace
11
21
  include_globs = ['**/*.rb']
12
22
  exclude_globs = ['spec/**/*', 'test/**/*']
23
+ @included = []
24
+ @excluded = []
25
+ @domains = []
13
26
  unless @workspace.nil?
27
+ include_globs = ['**/*.rb']
28
+ exclude_globs = ['spec/**/*', 'test/**/*']
14
29
  sfile = File.join(@workspace, '.solargraph.yml')
15
30
  if File.file?(sfile)
16
31
  @raw_data = YAML.load(File.read(sfile))
32
+ conf = YAML.load(File.read(sfile))
33
+ include_globs = conf['include'] || include_globs
34
+ exclude_globs = conf['exclude'] || []
35
+ @domains = conf['domains'] || []
17
36
  end
37
+ @included.concat process_globs(include_globs)
38
+ @excluded.concat process_globs(exclude_globs)
18
39
  end
19
40
  @raw_data ||= {}
20
41
  @raw_data['include'] = @raw_data['include'] || include_globs
21
42
  @raw_data['exclude'] = @raw_data['exclude'] || exclude_globs
22
- @raw_data['extensions'] = @raw_data['extensions'] || []
43
+ # @todo If the domains config goes stable, add it to @raw_data
23
44
  end
24
45
 
25
46
  def included
@@ -30,10 +51,6 @@ module Solargraph
30
51
  process_globs @raw_data['exclude']
31
52
  end
32
53
 
33
- def extensions
34
- @raw_data['extensions']
35
- end
36
-
37
54
  private
38
55
 
39
56
  def process_globs globs
@@ -44,7 +44,7 @@ module Solargraph
44
44
  attribute_pins.push Solargraph::Pin::Directed::Attribute.new(self, k.node, ns, :writer, docstring, "#{d.tag.name}=")
45
45
  end
46
46
  elsif d.tag.tag_name == 'method'
47
- gen_src = Source.virtual(filename, "def #{d.tag.name};end")
47
+ gen_src = Source.virtual("def #{d.tag.name};end", filename)
48
48
  gen_pin = gen_src.method_pins.first
49
49
  method_pins.push Solargraph::Pin::Directed::Method.new(gen_src, gen_pin.node, ns, :instance, :public, docstring, gen_pin.name)
50
50
  else
@@ -298,17 +298,17 @@ module Solargraph
298
298
  # @return [Solargraph::ApiMap::Source]
299
299
  def load filename
300
300
  code = File.read(filename).gsub(/\r/, '')
301
- Source.virtual(filename, code)
301
+ Source.virtual(code, filename)
302
302
  end
303
303
 
304
304
  # @return [Solargraph::ApiMap::Source]
305
- def virtual filename, code
305
+ def virtual code, filename = nil
306
306
  node, comments = Parser::CurrentRuby.parse_with_comments(code)
307
307
  Source.new(code, node, comments, filename)
308
308
  end
309
309
 
310
310
  # @return [Solargraph::ApiMap::Source]
311
- def fix filename, code, cursor = nil
311
+ def fix code, filename = nil, cursor = nil
312
312
  tries = 0
313
313
  code.gsub!(/\r/, '')
314
314
  tmp = code
@@ -31,9 +31,6 @@ module Solargraph
31
31
  # @return [String]
32
32
  attr_reader :workspace
33
33
 
34
- # @return [Array<String>]
35
- attr_reader :required
36
-
37
34
  # @param workspace [String]
38
35
  def initialize workspace = nil
39
36
  @workspace = workspace.gsub(/\\/, '/') unless workspace.nil?
@@ -59,14 +56,19 @@ module Solargraph
59
56
  @virtual_source = nil
60
57
  @virtual_filename = nil
61
58
  @stale = true
62
- live_map
63
59
  refresh
60
+ yard_map
64
61
  end
65
62
 
66
63
  def config
67
64
  @config ||= ApiMap::Config.new(@workspace)
68
65
  end
69
66
 
67
+ # @return [Array<String>]
68
+ def required
69
+ @required ||= []
70
+ end
71
+
70
72
  # @return [Solargraph::YardMap]
71
73
  def yard_map
72
74
  refresh
@@ -78,24 +80,25 @@ module Solargraph
78
80
 
79
81
  # @return [Solargraph::LiveMap]
80
82
  def live_map
81
- @live_map ||= Solargraph::LiveMap.new(workspace)
83
+ @live_map ||= Solargraph::LiveMap.new(self)
82
84
  end
83
85
 
84
86
  # @return [Solargraph::ApiMap::Source]
85
- def virtualize filename, code, cursor = nil
87
+ def virtualize code, filename = nil, cursor = nil
86
88
  unless @virtual_source.nil? or @virtual_filename == filename or @workspace_files.include?(@virtual_filename)
87
89
  eliminate @virtual_filename
88
90
  end
89
- refresh
91
+ #refresh
90
92
  @virtual_filename = filename
91
- @virtual_source = Source.fix(filename, code, cursor)
93
+ @virtual_source = Source.fix(code, filename, cursor)
92
94
  process_virtual
95
+ #@stale = true
93
96
  @virtual_source
94
97
  end
95
98
 
96
99
  # @return [Solargraph::ApiMap::Source]
97
100
  def append_source code, filename
98
- virtualize filename, code
101
+ virtualize code, filename
99
102
  end
100
103
 
101
104
  def refresh force = false
@@ -133,6 +136,8 @@ module Solargraph
133
136
  result = []
134
137
  result += inner_namespaces_in(name, root, [])
135
138
  result += yard_map.get_constants name, root
139
+ strings = result.map(&:to_s)
140
+ result.concat live_map.get_constants(name, root)
136
141
  result
137
142
  end
138
143
 
@@ -152,7 +157,7 @@ module Solargraph
152
157
  result.push pin_to_suggestion(pin)
153
158
  end
154
159
  end
155
- result.concat yard_map.get_constants(namespace, root)
160
+ result.concat yard_map.get_constants(fqns)
156
161
  end
157
162
 
158
163
  # @return [String]
@@ -188,7 +193,11 @@ module Solargraph
188
193
  }
189
194
  end
190
195
  end
191
- yard_map.find_fully_qualified_namespace(name, root)
196
+ result = yard_map.find_fully_qualified_namespace(name, root)
197
+ if result.nil?
198
+ result = live_map.get_fqns(name, root)
199
+ end
200
+ result
192
201
  end
193
202
 
194
203
  def get_namespace_nodes(fqns)
@@ -354,13 +363,16 @@ module Solargraph
354
363
  result
355
364
  end
356
365
 
357
- def get_namespace_type namespace, root = ''
366
+ def get_namespace_type fqns
367
+ return nil if fqns.nil?
358
368
  type = nil
359
- fqns = find_fully_qualified_namespace(namespace, root)
360
369
  nodes = get_namespace_nodes(fqns)
361
370
  unless nodes.nil? or nodes.empty? or !nodes[0].kind_of?(AST::Node)
362
371
  type = nodes[0].type if [:class, :module].include?(nodes[0].type)
363
372
  end
373
+ if type.nil?
374
+ type = yard_map.get_namespace_type(fqns)
375
+ end
364
376
  type
365
377
  end
366
378
 
@@ -373,15 +385,16 @@ module Solargraph
373
385
  namespace = clean_namespace_string(namespace)
374
386
  fqns = find_fully_qualified_namespace(namespace, root)
375
387
  meths = []
376
- meths.concat inner_get_methods(namespace, root, []) #unless has_yardoc?
377
- yard_meths = yard_map.get_methods(namespace, root, visibility: visibility)
388
+ skip = []
389
+ meths.concat inner_get_methods(namespace, root, skip)
390
+ yard_meths = yard_map.get_methods(fqns, '', visibility: visibility)
378
391
  if yard_meths.any?
379
392
  meths.concat yard_meths
380
393
  else
381
- type = get_namespace_type(namespace, root)
394
+ type = get_namespace_type(fqns)
382
395
  if type == :class
383
396
  meths.concat yard_map.get_instance_methods('Class')
384
- elsif type == :module
397
+ else
385
398
  meths.concat yard_map.get_methods('Module')
386
399
  end
387
400
  end
@@ -395,12 +408,17 @@ module Solargraph
395
408
  end
396
409
  end
397
410
  end
411
+ if namespace == '' and root == ''
412
+ config.domains.each do |d|
413
+ meths.concat get_instance_methods(d)
414
+ end
415
+ end
398
416
  strings = meths.map(&:to_s)
399
- live_map.get_methods(namespace, root, visibility.include?(:private)).each do |m|
417
+ live_map.get_methods(fqns, '', 'class', visibility.include?(:private)).each do |m|
400
418
  next if strings.include?(m) or !m.match(/^[a-z]/i)
401
- meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'))
419
+ meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}.#{m}")
402
420
  end
403
- meths
421
+ meths
404
422
  end
405
423
 
406
424
  # Get an array of instance methods that are available in the specified
@@ -420,7 +438,7 @@ module Solargraph
420
438
  if yard_meths.any?
421
439
  meths.concat yard_meths
422
440
  else
423
- type = get_namespace_type(namespace, root)
441
+ type = get_namespace_type(fqns)
424
442
  if type == :class
425
443
  meths += yard_map.get_instance_methods('Object')
426
444
  elsif type == :module
@@ -428,9 +446,9 @@ module Solargraph
428
446
  end
429
447
  end
430
448
  strings = meths.map(&:to_s)
431
- live_map.get_instance_methods(namespace, root, visibility.include?(:private)).each do |m|
449
+ live_map.get_methods(namespace, root, 'instance', visibility.include?(:private)).each do |m|
432
450
  next if strings.include?(m) or !m.match(/^[a-z]/i)
433
- meths.push Suggestion.new(m, kind: Suggestion::METHOD)
451
+ meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}##{m}")
434
452
  end
435
453
  meths
436
454
  end
@@ -448,8 +466,10 @@ module Solargraph
448
466
  end
449
467
 
450
468
  def update filename
451
- @@source_cache[filename] ||= Source.load(filename)
452
- #cache.clear
469
+ filename.gsub!(/\\/, '/')
470
+ eliminate filename
471
+ @@source_cache[filename] = Source.load(filename)
472
+ rebuild_local_yardoc #if @workspace_files.include?(filename)
453
473
  @stale = true
454
474
  end
455
475
 
@@ -467,7 +487,7 @@ module Solargraph
467
487
  elsif path.include?('.')
468
488
  # It's a class method
469
489
  parts = path.split('.')
470
- result = get_instance_methods(parts[0], '', visibility: [:public, :private, :protected]).select{|s| s.label == parts[1]}
490
+ result = get_methods(parts[0], '', visibility: [:public, :private, :protected]).select{|s| s.label == parts[1]}
471
491
  else
472
492
  # It's a class or module
473
493
  get_namespace_nodes(path).each do |node|
@@ -496,19 +516,11 @@ module Solargraph
496
516
  @parent_stack = {}
497
517
  namespace_map.clear
498
518
  namespace_tree.clear
499
- @required = []
519
+ required.clear
500
520
  end
501
521
 
502
522
  def process_maps
503
- @sources.clear
504
- @workspace_files.each do |f|
505
- begin
506
- @@source_cache[f] ||= Source.load(f)
507
- @sources[f] = @@source_cache[f]
508
- rescue
509
- STDERR.puts "Failed to load #{f}"
510
- end
511
- end
523
+ process_workspace_files
512
524
  cache.clear
513
525
  @ivar_pins = {}
514
526
  @cvar_pins = {}
@@ -537,11 +549,30 @@ module Solargraph
537
549
  map_source s
538
550
  }
539
551
  @required.uniq!
540
- #live_map.update self
541
- live_map.reload
552
+ live_map.refresh
542
553
  @stale = false
543
554
  end
544
555
 
556
+ def rebuild_local_yardoc
557
+ return if workspace.nil? or !File.exist?(File.join(workspace, '.yardoc'))
558
+ STDERR.puts "Rebuilding local yardoc for #{workspace}"
559
+ Dir.chdir(workspace) { Process.spawn('yardoc') }
560
+ end
561
+
562
+ def process_workspace_files
563
+ @sources.clear
564
+ @workspace_files.each do |f|
565
+ if File.file?(f)
566
+ begin
567
+ @@source_cache[f] ||= Source.load(f)
568
+ @sources[f] = @@source_cache[f]
569
+ rescue
570
+ STDERR.puts "Failed to load #{f}"
571
+ end
572
+ end
573
+ end
574
+ end
575
+
545
576
  def process_virtual
546
577
  unless @virtual_source.nil?
547
578
  cache.clear
@@ -629,9 +660,9 @@ module Solargraph
629
660
  meths.concat inner_get_methods(sc, fqns, skip, visibility - [:private])
630
661
  meths.concat yard_map.get_methods(sc, fqns, visibility: visibility - [:private])
631
662
  strings = meths.map(&:to_s)
632
- live_map.get_methods(sc, fqns, false).each do |m|
663
+ live_map.get_methods(sc, fqns, 'class', false).each do |m|
633
664
  next if strings.include?(m) or !m.match(/^[a-z]/i)
634
- meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'))
665
+ meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}##{m}")
635
666
  end
636
667
  end
637
668
  end
@@ -661,7 +692,7 @@ module Solargraph
661
692
  meths.concat inner_get_instance_methods(sc, fqns, skip, visibility - [:private])
662
693
  meths.concat yard_map.get_instance_methods(sc, fqns, visibility: visibility - [:private])
663
694
  strings = meths.map(&:to_s)
664
- live_map.get_instance_methods(sc, fqns, false).each do |m|
695
+ live_map.get_methods(sc, fqns, 'instance', false).each do |m|
665
696
  next if strings.include?(m) or !m.match(/^[a-z]/i)
666
697
  meths.push Suggestion.new(m, kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'))
667
698
  end
@@ -690,7 +721,7 @@ module Solargraph
690
721
  }
691
722
  unless cursor.nil?
692
723
  cursor.keys.each { |k|
693
- type = get_namespace_type(k, fqns)
724
+ type = get_namespace_type("#{fqns == '' ? '' : fqns + '::'}#{k}")
694
725
  kind = nil
695
726
  detail = nil
696
727
  if type == :class
@@ -755,10 +786,12 @@ module Solargraph
755
786
  visibility = [:public]
756
787
  visibility.concat [:private, :protected] if top
757
788
  if scope == :instance || namespace == ''
758
- meth = get_instance_methods(namespace, visibility: visibility).select{|s| s.label == part}.first
789
+ tmp = get_instance_methods(namespace, visibility: visibility)
759
790
  else
760
- meth = get_methods(namespace, visibility: visibility).select{|s| s.label == part}.first
791
+ tmp = get_methods(namespace, visibility: visibility)
761
792
  end
793
+ tmp.concat get_instance_methods('Kernel', visibility: [:public]) if top
794
+ meth = tmp.select{|s| s.label == part}.first
762
795
  return nil if meth.nil? or meth.return_type.nil?
763
796
  type = meth.return_type
764
797
  scope = :instance
@@ -37,7 +37,7 @@ module Solargraph
37
37
  filename = filename.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless filename.nil? or File::ALT_SEPARATOR.nil?
38
38
  @filename = filename
39
39
  @api_map = api_map
40
- @source = self.api_map.virtualize filename, code, cursor
40
+ @source = self.api_map.virtualize code, filename, cursor
41
41
  @node = @source.node
42
42
  @code = @source.code
43
43
  @comments = @source.comments
@@ -229,8 +229,7 @@ module Solargraph
229
229
  else
230
230
  type = infer_literal_node_type(node_at(index - 2))
231
231
  if type.nil?
232
- current_namespace = namespace_at(index)
233
- parts = current_namespace.to_s.split('::')
232
+ parts = namespace.to_s.split('::')
234
233
  result += get_snippets_at(index) if with_snippets
235
234
  result += get_local_variables_and_methods_at(index)
236
235
  result += ApiMap.get_keywords
@@ -652,7 +651,7 @@ module Solargraph
652
651
  arr = []
653
652
  @source.local_variable_pins.select{|p| p.visible_from?(node) }.each do |pin|
654
653
  #arr.push Suggestion.new(pin.name, kind: Suggestion::VARIABLE, return_type: api_map.infer_assignment_node_type(pin.node, namespace))
655
- arr.push Suggestion.new(pin.name, kind: Suggestion::VARIABLE)
654
+ arr.push Suggestion.new(pin.name, kind: Suggestion::VARIABLE, location: pin.location)
656
655
  end
657
656
  arr
658
657
  end
@@ -3,7 +3,7 @@ module Solargraph
3
3
  class Cache
4
4
  def initialize
5
5
  @method_cache = {}
6
- @instance_method_cache = {}
6
+ @constant_cache = {}
7
7
  end
8
8
 
9
9
  def get_methods options
@@ -14,17 +14,17 @@ module Solargraph
14
14
  @method_cache[options] = values
15
15
  end
16
16
 
17
- def get_instance_methods options
18
- @instance_method_cache[options]
17
+ def get_constants namespace, root
18
+ @constant_cache[[namespace, root]]
19
19
  end
20
20
 
21
- def set_instance_methods options, values
22
- @instance_method_cache[options] = values
21
+ def set_constants namespace, root, values
22
+ @constant_cache[[namespace, root]] = values
23
23
  end
24
24
 
25
25
  def clear
26
26
  @method_cache.clear
27
- @instance_method_cache.clear
27
+ @constant_cache.clear
28
28
  end
29
29
  end
30
30
  end
@@ -2,95 +2,125 @@ module Solargraph
2
2
  # The LiveMap allows extensions to add their own completion suggestions.
3
3
  #
4
4
  class LiveMap
5
+ autoload :Cache, 'solargraph/live_map/cache'
6
+
5
7
  @@plugins = []
6
-
7
- attr_reader :workspace
8
8
 
9
- def initialize workspace
10
- @workspace = workspace
11
- @runners = []
12
- at_exit { stop }
9
+ # @return [Solargraph::ApiMap]
10
+ attr_reader :api_map
11
+
12
+ def initialize api_map
13
+ @api_map = api_map
14
+ runners
13
15
  end
14
16
 
15
- def start
16
- unless workspace.nil?
17
- @@plugins.each do |p|
18
- r = p.new(workspace)
19
- r.start
20
- @runners.push r
21
- end
17
+ def get_methods(namespace, root = '', scope = 'instance', with_private = false)
18
+ params = {
19
+ namespace: namespace, root: root, scope: scope, with_private: with_private
20
+ }
21
+ cached = cache.get_methods(params)
22
+ return cached unless cached.nil?
23
+ did_runtime = false
24
+ result = []
25
+ runners.each do |p|
26
+ next if did_runtime and p.runtime?
27
+ result.concat p.get_methods(namespace: namespace, root: root, scope: scope, with_private: with_private)
28
+ did_runtime = true if p.runtime?
22
29
  end
30
+ cache.set_methods(params, result)
31
+ result
23
32
  end
24
33
 
25
- def reload
26
- restart
34
+ # @return [Array<Solargraph::Suggestion>]
35
+ def get_constants(namespace, root = '')
36
+ cached = cache.get_constants(namespace, root)
37
+ return cached unless cached.nil?
38
+ did_runtime = false
39
+ result = []
40
+ runners.each do |p|
41
+ next if did_runtime and p.runtime?
42
+ result.concat p.get_constants(namespace, root)
43
+ did_runtime = true if p.runtime?
44
+ end
45
+ suggestions = []
46
+ result.uniq.each do |r|
47
+ kind = Suggestion::CONSTANT
48
+ if r['class'] == 'Class'
49
+ kind = Suggestion::CLASS
50
+ elsif r['class'] == 'Module'
51
+ kind = Suggestion::MODULE
52
+ end
53
+ suggestions.push(Suggestion.new(r['name'], kind: kind))
54
+ end
55
+ cache.set_constants(namespace, root, suggestions)
56
+ suggestions
27
57
  end
28
58
 
29
- def restart
30
- stop
31
- start
59
+ def get_fqns(namespace, root)
60
+ did_runtime = false
61
+ runners.each do |p|
62
+ next if did_runtime and p.runtime?
63
+ result = p.get_fqns(namespace, root)
64
+ return result unless result.nil?
65
+ did_runtime = true if p.runtime?
66
+ end
67
+ nil
32
68
  end
33
69
 
34
- def stop
35
- @runners.each do |p|
36
- p.stop
37
- end
38
- @runners.clear
70
+ # Register a plugin for LiveMap to use when generating suggestions.
71
+ #
72
+ # @param cls [Class<Solargraph::Plugin::Base>]
73
+ def self.install cls
74
+ @@plugins.push cls unless @@plugins.include?(cls)
39
75
  end
40
76
 
41
- def get_instance_methods(namespace, root = '', with_private = false)
42
- result = []
43
- @runners.each do |p|
44
- resp = p.get_methods(namespace: namespace, root: root, scope: 'instance', with_private: with_private)
45
- STDERR.puts resp.message unless resp.ok?
46
- result.concat(resp.data)
47
- end
48
- result
77
+ def self.uninstall cls
78
+ @@plugins.delete cls
49
79
  end
50
80
 
51
- def get_methods(namespace, root = '', with_private = false)
52
- result = []
53
- @runners.each do |p|
54
- resp = p.get_methods(namespace: namespace, root: root, scope: 'class', with_private: with_private)
55
- STDERR.puts resp.message unless resp.ok?
56
- result.concat(resp.data)
57
- end
58
- result
81
+ def self.plugins
82
+ @@plugins.clone
59
83
  end
60
84
 
61
- def self.install cls
62
- @@plugins.push cls
85
+ def refresh
86
+ changed = false
87
+ runners.each do |p|
88
+ changed ||= p.refresh
89
+ end
90
+ if changed
91
+ STDERR.puts "Resetting LiveMap cache"
92
+ cache.clear
93
+ get_constants('')
94
+ get_methods('', '', 'class')
95
+ get_methods('', '', 'instance')
96
+ get_methods('Kernel', '', 'class')
97
+ get_methods('Kernel', '', 'instance')
98
+ end
63
99
  end
64
100
 
65
101
  private
66
102
 
67
- def find_constant(namespace, root)
68
- result = nil
69
- parts = root.split('::')
70
- if parts.empty?
71
- result = inner_find_constant(namespace)
72
- else
73
- until parts.empty?
74
- result = inner_find_constant("#{parts.join('::')}::#{namespace}")
75
- break unless result.nil?
76
- parts.pop
77
- end
78
- end
79
- result
103
+ # @return [Solargraph::LiveMap::Cache]
104
+ def cache
105
+ @cache ||= Solargraph::LiveMap::Cache.new
80
106
  end
81
107
 
82
- def inner_find_constant(namespace)
83
- cursor = Object
84
- parts = namespace.split('::')
85
- until parts.empty?
86
- here = parts.shift
87
- begin
88
- cursor = cursor.const_get(here)
89
- rescue NameError
90
- return nil
91
- end
108
+ # @return [Array<Solargraph::Plugin::Base>]
109
+ def runners
110
+ @runners ||= load_runners
111
+ end
112
+
113
+ # @return [Array<Solargraph::Plugin::Base>]
114
+ def load_runners
115
+ result = []
116
+ has_runtime = false
117
+ @@plugins.each do |p|
118
+ r = p.new(api_map)
119
+ result.push r if !has_runtime or !r.runtime?
120
+ has_runtime = true if r.runtime?
92
121
  end
93
- cursor
122
+ result.push Solargraph::Plugin::Runtime.new(api_map) unless has_runtime
123
+ result
94
124
  end
95
125
  end
96
126
  end
@@ -60,6 +60,10 @@ module Solargraph
60
60
  def filename
61
61
  source.filename
62
62
  end
63
+
64
+ def location
65
+ "#{source.filename}:#{node.location.expression.begin_pos}"
66
+ end
63
67
  end
64
68
  end
65
69
  end