solargraph 0.39.13 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -7
  3. data/CHANGELOG.md +984 -0
  4. data/Rakefile +12 -1
  5. data/SPONSORS.md +1 -0
  6. data/lib/solargraph.rb +2 -4
  7. data/lib/solargraph/api_map.rb +75 -74
  8. data/lib/solargraph/api_map/cache.rb +2 -2
  9. data/lib/solargraph/api_map/store.rb +4 -8
  10. data/lib/solargraph/{bundle.rb → bench.rb} +6 -2
  11. data/lib/solargraph/compat.rb +14 -0
  12. data/lib/solargraph/complex_type.rb +2 -2
  13. data/lib/solargraph/convention.rb +14 -5
  14. data/lib/solargraph/convention/base.rb +16 -8
  15. data/lib/solargraph/convention/gemfile.rb +2 -5
  16. data/lib/solargraph/convention/gemspec.rb +3 -6
  17. data/lib/solargraph/convention/rspec.rb +3 -6
  18. data/lib/solargraph/documentor.rb +2 -0
  19. data/lib/solargraph/environ.rb +11 -6
  20. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +6 -1
  21. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  22. data/lib/solargraph/library.rb +7 -7
  23. data/lib/solargraph/parser/legacy/node_chainer.rb +7 -7
  24. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +1 -1
  25. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +36 -23
  26. data/lib/solargraph/parser/node_processor/base.rb +3 -0
  27. data/lib/solargraph/parser/rubyvm/node_chainer.rb +9 -9
  28. data/lib/solargraph/parser/rubyvm/node_methods.rb +1 -1
  29. data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
  30. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +35 -11
  31. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +1 -1
  32. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +40 -29
  33. data/lib/solargraph/pin.rb +0 -3
  34. data/lib/solargraph/pin/common.rb +1 -1
  35. data/lib/solargraph/pin/conversions.rb +3 -4
  36. data/lib/solargraph/pin/documenting.rb +3 -9
  37. data/lib/solargraph/pin/method.rb +141 -7
  38. data/lib/solargraph/pin/method_alias.rb +1 -1
  39. data/lib/solargraph/position.rb +2 -14
  40. data/lib/solargraph/shell.rb +1 -0
  41. data/lib/solargraph/source.rb +10 -6
  42. data/lib/solargraph/source/chain.rb +18 -5
  43. data/lib/solargraph/source_map.rb +4 -1
  44. data/lib/solargraph/source_map/clip.rb +3 -2
  45. data/lib/solargraph/source_map/mapper.rb +10 -6
  46. data/lib/solargraph/type_checker.rb +35 -39
  47. data/lib/solargraph/type_checker/param_def.rb +1 -1
  48. data/lib/solargraph/version.rb +1 -1
  49. data/lib/solargraph/yard_map.rb +40 -47
  50. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  51. data/lib/solargraph/yard_map/helpers.rb +16 -0
  52. data/lib/solargraph/yard_map/mapper.rb +14 -8
  53. data/lib/solargraph/{pin/yard_pin/constant.rb → yard_map/mapper/to_constant.rb} +6 -6
  54. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  55. data/lib/solargraph/{pin/yard_pin/namespace.rb → yard_map/mapper/to_namespace.rb} +6 -6
  56. data/lib/solargraph/yard_map/rdoc_to_yard.rb +1 -1
  57. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  58. data/lib/solargraph/yard_map/to_method.rb +79 -0
  59. data/solargraph.gemspec +4 -4
  60. metadata +20 -34
  61. data/lib/solargraph/core_fills.rb +0 -159
  62. data/lib/solargraph/pin/attribute.rb +0 -49
  63. data/lib/solargraph/pin/base_method.rb +0 -141
  64. data/lib/solargraph/pin/yard_pin.rb +0 -12
  65. data/lib/solargraph/pin/yard_pin/method.rb +0 -80
  66. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +0 -20
  67. data/lib/solargraph/stdlib_fills.rb +0 -40
  68. data/travis-bundler.rb +0 -11
@@ -4,18 +4,22 @@ module Solargraph
4
4
  # An aggregation of a workspace and additional sources to be cataloged in an
5
5
  # ApiMap.
6
6
  #
7
- class Bundle
7
+ class Bench
8
8
  # @return [Workspace]
9
9
  attr_reader :workspace
10
10
 
11
11
  # @return [Array<Source>]
12
12
  attr_reader :opened
13
13
 
14
+ # @return [Array<Pin::Base>]
15
+ attr_reader :pins
16
+
14
17
  # @param workspace [Workspace]
15
18
  # @param opened [Array<Source>]
16
- def initialize workspace: Workspace.new, opened: []
19
+ def initialize workspace: Workspace.new, opened: [], pins: []
17
20
  @workspace = workspace
18
21
  @opened = opened
22
+ @pins = pins
19
23
  end
20
24
 
21
25
  # @return [Array<Source>]
@@ -7,3 +7,17 @@ unless Hash.method_defined?(:transform_values)
7
7
  end
8
8
  end
9
9
  end
10
+
11
+ unless Array.method_defined?(:sum)
12
+ class Array
13
+ def sum &block
14
+ inject(0) do |s, x|
15
+ if block
16
+ s + block.call(x)
17
+ else
18
+ s + x
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -12,7 +12,7 @@ module Solargraph
12
12
 
13
13
  # @param types [Array<UniqueType>]
14
14
  def initialize types = [UniqueType::UNDEFINED]
15
- @items = types
15
+ @items = types.uniq(&:to_s)
16
16
  end
17
17
 
18
18
  # @param api_map [ApiMap]
@@ -113,7 +113,7 @@ module Solargraph
113
113
  #
114
114
  # @param *strings [Array<String>] The type definitions to parse
115
115
  # @param partial [Boolean] True if the string is part of a another type
116
- # @return [ComplexType]
116
+ # @return [ComplexType, Array, nil]
117
117
  def parse *strings, partial: false
118
118
  @cache ||= {}
119
119
  unless partial
@@ -15,18 +15,27 @@ module Solargraph
15
15
  @@conventions = Set.new
16
16
 
17
17
  # @param convention [Class<Convention::Base>]
18
- # @return [Convention::Base]
18
+ # @return [void]
19
19
  def self.register convention
20
20
  @@conventions.add convention.new
21
21
  end
22
22
 
23
- # @param source [Source]
23
+ # @param source_map [SourceMap]
24
24
  # @return [Environ]
25
- def self.for(source)
25
+ def self.for_local(source_map)
26
26
  result = Environ.new
27
- return result if source.filename.nil? || source.filename.empty?
28
27
  @@conventions.each do |conv|
29
- result.merge conv.environ if conv.match?(source)
28
+ result.merge conv.local(source_map)
29
+ end
30
+ result
31
+ end
32
+
33
+ # @param yard_map [YardMap]
34
+ # @return [Environ]
35
+ def self.for_global(yard_map)
36
+ result = Environ.new
37
+ @@conventions.each do |conv|
38
+ result.merge conv.global(yard_map)
30
39
  end
31
40
  result
32
41
  end
@@ -2,22 +2,30 @@
2
2
 
3
3
  module Solargraph
4
4
  module Convention
5
+ # The base class for Conventions.
6
+ #
7
+ # A Convention provides Environs that customize ApiMaps with additional
8
+ # pins and other information. Subclasses should implement the `local` and
9
+ # `global` methods as necessary.
10
+ #
5
11
  class Base
6
12
  EMPTY_ENVIRON = Environ.new
7
13
 
8
- # True if the source qualifies for this convention.
9
- # Subclasses should override this method.
14
+ # The Environ for a source map.
15
+ # Subclasses can override this method.
10
16
  #
11
- # @param source [Source]
12
- def match? source
13
- false
17
+ # @param source_map [SourceMap]
18
+ # @return [Environ]
19
+ def local source_map
20
+ EMPTY_ENVIRON
14
21
  end
15
22
 
16
- # The Environ for this convention.
17
- # Subclasses should override this method.
23
+ # The Environ for a YARD map.
24
+ # Subclasses can override this method.
18
25
  #
26
+ # @param yard_map [YardMap]
19
27
  # @return [Environ]
20
- def environ
28
+ def global yard_map
21
29
  EMPTY_ENVIRON
22
30
  end
23
31
  end
@@ -3,11 +3,8 @@
3
3
  module Solargraph
4
4
  module Convention
5
5
  class Gemfile < Base
6
- def match? source
7
- File.basename(source.filename) == 'Gemfile'
8
- end
9
-
10
- def environ
6
+ def local source_map
7
+ return EMPTY_ENVIRON unless File.basename(source_map.filename) == 'Gemfile'
11
8
  @environ ||= Environ.new(
12
9
  requires: ['bundler'],
13
10
  domains: ['Bundler::Dsl']
@@ -3,14 +3,11 @@
3
3
  module Solargraph
4
4
  module Convention
5
5
  class Gemspec < Base
6
- def match? source
7
- File.basename(source.filename).end_with?('.gemspec')
8
- end
9
-
10
- def environ
6
+ def local source_map
7
+ return EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
11
8
  @environ ||= Environ.new(
12
9
  requires: ['rubygems'],
13
- overrides: [
10
+ pins: [
14
11
  Solargraph::Pin::Reference::Override.from_comment(
15
12
  'Gem::Specification.new',
16
13
  %(
@@ -3,18 +3,15 @@
3
3
  module Solargraph
4
4
  module Convention
5
5
  class Rspec < Base
6
- def match? source
7
- File.basename(source.filename) =~ /_spec\.rb$/
8
- end
9
-
10
- def environ
6
+ def local source_map
7
+ return EMPTY_ENVIRON unless File.basename(source_map.filename) =~ /_spec\.rb$/
11
8
  @environ ||= Environ.new(
12
9
  requires: ['rspec'],
13
10
  domains: ['RSpec::Matchers', 'RSpec::ExpectationGroups'],
14
11
  # This override is necessary due to an erroneous @return tag in
15
12
  # rspec's YARD documentation.
16
13
  # @todo The return types have been fixed (https://github.com/rspec/rspec-expectations/pull/1121)
17
- overrides: [
14
+ pins: [
18
15
  Solargraph::Pin::Reference::Override.method_return('RSpec::Matchers#expect', 'RSpec::Expectations::ExpectationTarget')
19
16
  ]
20
17
  )
@@ -55,6 +55,8 @@ module Solargraph
55
55
  false
56
56
  end
57
57
 
58
+ # @param directory [String]
59
+ # @return [Hash]
58
60
  def self.specs_from_bundle directory
59
61
  Solargraph.with_clean_env do
60
62
  Dir.chdir directory do
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
+ # A collection of additional data, such as map pins and required paths, that
5
+ # can be added to an ApiMap.
6
+ #
7
+ # Conventions are used to add Environs.
8
+ #
4
9
  class Environ
5
10
  # @return [Array<String>]
6
11
  attr_reader :requires
@@ -9,22 +14,22 @@ module Solargraph
9
14
  attr_reader :domains
10
15
 
11
16
  # @return [Array<Pin::Reference::Override>]
12
- attr_reader :overrides
17
+ attr_reader :pins
13
18
 
14
19
  # @param requires [Array<String>]
15
20
  # @param domains [Array<String>]
16
- # @param overrides [Array<Pin::Reference::Override>]
17
- def initialize requires: [], domains: [], overrides: []
21
+ # @param pins [Array<Pin::Base>]
22
+ def initialize requires: [], domains: [], pins: []
18
23
  @requires = requires
19
24
  @domains = domains
20
- @overrides = overrides
25
+ @pins = pins
21
26
  end
22
27
 
23
28
  # @return [self]
24
29
  def clear
25
30
  domains.clear
26
31
  requires.clear
27
- overrides.clear
32
+ pins.clear
28
33
  self
29
34
  end
30
35
 
@@ -33,7 +38,7 @@ module Solargraph
33
38
  def merge other
34
39
  domains.concat other.domains
35
40
  requires.concat other.requires
36
- overrides.concat other.overrides
41
+ pins.concat other.pins
37
42
  self
38
43
  end
39
44
  end
@@ -34,7 +34,12 @@ module Solargraph
34
34
  LanguageServer::MessageTypes::INFO,
35
35
  ['Update now'] do |result|
36
36
  next unless result == 'Update now'
37
- o, s = Open3.capture2("gem update solargraph")
37
+ cmd = if host.options['useBundler']
38
+ 'bundle update solargraph'
39
+ else
40
+ 'gem update solargraph'
41
+ end
42
+ o, s = Open3.capture2(cmd)
38
43
  if s == 0
39
44
  host.show_message 'Successfully updated the Solargraph gem.', LanguageServer::MessageTypes::INFO
40
45
  host.send_notification '$/solargraph/restart', {}
@@ -13,7 +13,7 @@ module Solargraph::LanguageServer::Message::TextDocument
13
13
  def code_location
14
14
  suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
15
15
  return nil if suggestions.empty?
16
- suggestions.reject{|pin| pin.location.nil?}.map do |pin|
16
+ suggestions.reject { |pin| pin.location.nil? || pin.location.filename.nil? }.map do |pin|
17
17
  {
18
18
  uri: file_to_uri(pin.location.filename),
19
19
  range: pin.location.range.to_hash
@@ -20,7 +20,7 @@ module Solargraph
20
20
  def initialize workspace = Solargraph::Workspace.new, name = nil
21
21
  @workspace = workspace
22
22
  @name = name
23
- api_map.catalog bundle
23
+ api_map.catalog bench
24
24
  @synchronized = true
25
25
  @catalog_mutex = Mutex.new
26
26
  end
@@ -174,10 +174,10 @@ module Solargraph
174
174
  if cursor.comment?
175
175
  source = read(filename)
176
176
  offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
177
- lft = source.code[0..offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
177
+ lft = source.code[0..offset-1].match(/\[[a-z0-9_:<, ]*?([a-z0-9_:]*)\z/i)
178
178
  rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?[\]>, ]/i)
179
179
  if lft && rgt
180
- tag = lft[1] + rgt[1]
180
+ tag = (lft[1] + rgt[1]).sub(/:+$/, '')
181
181
  clip = api_map.clip(cursor)
182
182
  clip.translate tag
183
183
  else
@@ -351,7 +351,7 @@ module Solargraph
351
351
  @catalog_mutex.synchronize do
352
352
  break if synchronized?
353
353
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
354
- api_map.catalog bundle
354
+ api_map.catalog bench
355
355
  @synchronized = true
356
356
  logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" if logger.info?
357
357
  end
@@ -403,9 +403,9 @@ module Solargraph
403
403
  @api_map ||= Solargraph::ApiMap.new
404
404
  end
405
405
 
406
- # @return [Bundle]
407
- def bundle
408
- Bundle.new(
406
+ # @return [Bench]
407
+ def bench
408
+ Bench.new(
409
409
  workspace: workspace,
410
410
  opened: @current ? [@current] : []
411
411
  )
@@ -14,7 +14,7 @@ module Solargraph
14
14
  def initialize node, filename = nil, in_block = false
15
15
  @node = node
16
16
  @filename = filename
17
- @in_block = in_block
17
+ @in_block = in_block ? 1 : 0
18
18
  end
19
19
 
20
20
  # @return [Source::Chain]
@@ -51,9 +51,9 @@ module Solargraph
51
51
  return generate_links(n.children[0]) if n.type == :splat
52
52
  result = []
53
53
  if n.type == :block
54
- @in_block = true
54
+ @in_block += 1
55
55
  result.concat generate_links(n.children[0])
56
- @in_block = false
56
+ @in_block -= 1
57
57
  elsif n.type == :send
58
58
  if n.children[0].is_a?(::Parser::AST::Node)
59
59
  result.concat generate_links(n.children[0])
@@ -61,23 +61,23 @@ module Solargraph
61
61
  n.children[2..-1].each do |c|
62
62
  args.push NodeChainer.chain(c)
63
63
  end
64
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
64
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
65
65
  elsif n.children[0].nil?
66
66
  args = []
67
67
  n.children[2..-1].each do |c|
68
68
  args.push NodeChainer.chain(c)
69
69
  end
70
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
70
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
71
71
  else
72
72
  raise "No idea what to do with #{n}"
73
73
  end
74
74
  elsif n.type == :self
75
75
  result.push Chain::Head.new('self')
76
76
  elsif n.type == :zsuper
77
- result.push Chain::ZSuper.new('super', @in_block || block_passed?(n))
77
+ result.push Chain::ZSuper.new('super', @in_block > 0 || block_passed?(n))
78
78
  elsif n.type == :super
79
79
  args = n.children.map { |c| NodeChainer.chain(c) }
80
- result.push Chain::Call.new('super', args, @in_block || block_passed?(n))
80
+ result.push Chain::Call.new('super', args, @in_block > 0 || block_passed?(n))
81
81
  elsif n.type == :const
82
82
  const = unpack_name(n)
83
83
  result.push Chain::Constant.new(const)
@@ -19,7 +19,7 @@ module Solargraph
19
19
  if region.visibility == :module_function
20
20
  here = get_node_start_position(node)
21
21
  named_path = named_path_pin(here)
22
- if named_path.is_a?(Pin::BaseMethod)
22
+ if named_path.is_a?(Pin::Method)
23
23
  pins.push Solargraph::Pin::InstanceVariable.new(
24
24
  location: loc,
25
25
  closure: Pin::Namespace.new(type: :module, closure: region.closure.closure, name: region.closure.name),
@@ -10,20 +10,7 @@ module Solargraph
10
10
  def process
11
11
  if node.children[0].nil?
12
12
  if [:private, :public, :protected].include?(node.children[1])
13
- if (node.children.length > 2)
14
- node.children[2..-1].each do |child|
15
- next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
16
- name = child.children[0].to_s
17
- matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
18
- matches.each do |pin|
19
- # @todo Smelly instance variable access
20
- pin.instance_variable_set(:@visibility, node.children[1])
21
- end
22
- end
23
- else
24
- # @todo Smelly instance variable access
25
- region.instance_variable_set(:@visibility, node.children[1])
26
- end
13
+ process_visibility
27
14
  elsif node.children[1] == :module_function
28
15
  process_module_function
29
16
  elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[1])
@@ -54,6 +41,27 @@ module Solargraph
54
41
 
55
42
  private
56
43
 
44
+ # @return [void]
45
+ def process_visibility
46
+ if (node.children.length > 2)
47
+ node.children[2..-1].each do |child|
48
+ if child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
49
+ name = child.children[0].to_s
50
+ matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
51
+ matches.each do |pin|
52
+ # @todo Smelly instance variable access
53
+ pin.instance_variable_set(:@visibility, node.children[1])
54
+ end
55
+ else
56
+ process_children region.update(visibility: node.children[1])
57
+ end
58
+ end
59
+ else
60
+ # @todo Smelly instance variable access
61
+ region.instance_variable_set(:@visibility, node.children[1])
62
+ end
63
+ end
64
+
57
65
  # @return [void]
58
66
  def process_attribute
59
67
  node.children[2..-1].each do |a|
@@ -61,26 +69,30 @@ module Solargraph
61
69
  clos = region.closure
62
70
  cmnt = comments_for(node)
63
71
  if node.children[1] == :attr_reader || node.children[1] == :attr_accessor
64
- pins.push Solargraph::Pin::Attribute.new(
72
+ pins.push Solargraph::Pin::Method.new(
65
73
  location: loc,
66
74
  closure: clos,
67
75
  name: a.children[0].to_s,
68
76
  comments: cmnt,
69
- access: :reader,
70
77
  scope: region.scope || :instance,
71
- visibility: region.visibility
78
+ visibility: region.visibility,
79
+ attribute: true
72
80
  )
73
81
  end
74
82
  if node.children[1] == :attr_writer || node.children[1] == :attr_accessor
75
- pins.push Solargraph::Pin::Attribute.new(
83
+ pins.push Solargraph::Pin::Method.new(
76
84
  location: loc,
77
85
  closure: clos,
78
86
  name: "#{a.children[0]}=",
79
87
  comments: cmnt,
80
- access: :writer,
81
88
  scope: region.scope || :instance,
82
- visibility: region.visibility
89
+ visibility: region.visibility,
90
+ attribute: true
83
91
  )
92
+ pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
93
+ if pins.last.return_type.defined?
94
+ pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
95
+ end
84
96
  end
85
97
  end
86
98
  end
@@ -90,7 +102,8 @@ module Solargraph
90
102
  if node.children[2].is_a?(AST::Node) && node.children[2].type == :const
91
103
  cp = region.closure
92
104
  node.children[2..-1].each do |i|
93
- pins.push Pin::Reference::Include.new(
105
+ type = region.scope == :class ? Pin::Reference::Extend : Pin::Reference::Include
106
+ pins.push type.new(
94
107
  location: get_node_location(i),
95
108
  closure: cp,
96
109
  name: unpack_name(i)
@@ -156,7 +169,7 @@ module Solargraph
156
169
  elsif node.children[2].type == :sym || node.children[2].type == :str
157
170
  node.children[2..-1].each do |x|
158
171
  cn = x.children[0].to_s
159
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == cn}.first
172
+ ref = pins.select{ |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == cn }.first
160
173
  unless ref.nil?
161
174
  pins.delete ref
162
175
  mm = Solargraph::Pin::Method.new(
@@ -228,7 +241,7 @@ module Solargraph
228
241
  # @return [Boolean]
229
242
  def process_private_class_method
230
243
  if node.children[2].type == :sym || node.children[2].type == :str
231
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == node.children[2].children[0].to_s}.first
244
+ ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == node.children[2].children[0].to_s }.first
232
245
  # HACK: Smelly instance variable access
233
246
  ref.instance_variable_set(:@visibility, :private) unless ref.nil?
234
247
  false