solargraph 0.34.3 → 0.35.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
  SHA256:
3
- metadata.gz: 19d601d06fae9aedf33e93d09172bb9257757aaf7323f6f6a355c82fc7b67223
4
- data.tar.gz: 5a5d073284cd8034b710dbb22169a30478e490e8561b4e2be56b59a52c79b757
3
+ metadata.gz: 02a0b8dd485332480c292f17a1cae69217cf9cb4e5f3aa9c29bd94ac55d57ab8
4
+ data.tar.gz: f74891d9e13561d6a1ece0fb64fd014af2b1504e412e9d51b4e83d8d6a9aa089
5
5
  SHA512:
6
- metadata.gz: 0071a0c809fae4043ea2ffa35ef811f575d1c9027f199c47d344692ce0e7a641a10f94af240220959a5ef924f92985511afebd8b502cc35ed023bbffe2b27a62
7
- data.tar.gz: 0076f43c9ae828ead40ec6d64a6409fa96d3631a290673baf026aa65e8f72fbdc8103cd073a7f5919945cd8a7f598f233889ef38ea173f3e58cd27cbb03f8812
6
+ metadata.gz: f3c8574a741707ef88be3f6ec1e1287b4a67b091d0c12634e65d563e93510ba135c193b55f9f4d05af5a5f8b1d9a6c661f691e571811281cd523c6a62eec5513
7
+ data.tar.gz: 13a013bcc7738c449696207a3622e1b3d3b7bed626fd2e39fe2a89c08eb42776fd19a32c7d65642b4ada6535a94af0f3f0a6ea3aee303eba1c2407daff9d4ad9
@@ -73,6 +73,8 @@ module Solargraph
73
73
  @items.any?(&:selfy?)
74
74
  end
75
75
 
76
+ # @param dst [String]
77
+ # @return [ComplexType]
76
78
  def self_to dst
77
79
  return self unless selfy?
78
80
  red = reduce_class(dst)
@@ -86,6 +88,8 @@ module Solargraph
86
88
  # to reference an instance of their class and never the class itself.
87
89
  # This behavior may change depending on which result is expected
88
90
  # from YARD conventions. See https://github.com/lsegal/yard/issues/1257
91
+ # @param dst [String]
92
+ # @return [String]
89
93
  def reduce_class dst
90
94
  while dst =~ /^(Class|Module)\<(.*?)\>$/
91
95
  dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
@@ -21,10 +21,14 @@ module Solargraph
21
21
  ]
22
22
 
23
23
  OVERRIDES = [
24
- Override.method_return('Array#select', 'self'),
25
- Override.method_return('Array#reject', 'self'),
26
24
  Override.method_return('Array#keep_if', 'self'),
27
25
  Override.method_return('Array#delete_if', 'self'),
26
+ Override.from_comment('Array#reject', %(
27
+ @overload reject(&block)
28
+ @return [self]
29
+ @overload reject()
30
+ @return [Enumerator]
31
+ )),
28
32
  Override.method_return('Array#reverse', 'self', delete: ['overload']),
29
33
  Override.from_comment('Array#select', %(
30
34
  @overload select(&block)
@@ -76,6 +80,7 @@ module Solargraph
76
80
  Override.method_return('Object#dup', 'self'),
77
81
  Override.method_return('Object#freeze', 'self'),
78
82
  Override.method_return('Object#taint', 'self'),
83
+ Override.method_return('Object#to_s', 'String'),
79
84
  Override.method_return('Object#untaint', 'self'),
80
85
  Override.from_comment('Object#tap', %(
81
86
  @return [self]
@@ -9,6 +9,8 @@ require 'cgi'
9
9
  module Solargraph
10
10
  class Page
11
11
  class Binder < OpenStruct
12
+ # @param locals [Hash]
13
+ # @param render_method [Proc]
12
14
  def initialize locals, render_method
13
15
  super(locals)
14
16
  define_singleton_method :render do |template, layout: false, locals: {}|
@@ -19,6 +21,8 @@ module Solargraph
19
21
  end
20
22
  end
21
23
 
24
+ # @param text [String]
25
+ # @return [String]
22
26
  def htmlify text
23
27
  Kramdown::Document.new(
24
28
  text.to_s.lines.map{|l| l.gsub(/^ /, "\t")}.join,
@@ -33,16 +37,23 @@ module Solargraph
33
37
  ).to_html
34
38
  end
35
39
 
40
+ # @param code [String]
41
+ # @return [String]
36
42
  def ruby_to_html code
37
43
  code
38
44
  end
39
45
  end
40
46
  private_constant :Binder
41
47
 
48
+ # @param directory [String]
42
49
  def initialize directory = VIEWS_PATH
43
50
  directory = VIEWS_PATH if directory.nil? or !File.directory?(directory)
44
51
  directories = [directory]
45
52
  directories.push VIEWS_PATH if directory != VIEWS_PATH
53
+ # @type [Proc]
54
+ # @param template [String]
55
+ # @param layout [Boolean]
56
+ # @param locals [Hash]
46
57
  @render_method = proc { |template, layout: false, locals: {}|
47
58
  binder = Binder.new(locals, @render_method)
48
59
  if layout
@@ -55,10 +66,17 @@ module Solargraph
55
66
  }
56
67
  end
57
68
 
69
+ # @param template [String]
70
+ # @param layout [Boolean]
71
+ # @param locals [Hash]
72
+ # @return [String]
58
73
  def render template, layout: true, locals: {}
59
74
  @render_method.call(template, layout: layout, locals: locals)
60
75
  end
61
76
 
77
+ # @param directories [Array<String>]
78
+ # @param name [String]
79
+ # @return [String]
62
80
  def self.select_template directories, name
63
81
  directories.each do |dir|
64
82
  path = File.join(dir, "#{name}.erb")
@@ -236,7 +236,8 @@ module Solargraph
236
236
 
237
237
  # @return [void]
238
238
  def parse_comments
239
- if comments.empty?
239
+ # HACK: Avoid a NoMethodError on nil with empty overload tags
240
+ if comments.empty? || comments.strip.end_with?('@overload')
240
241
  @docstring = nil
241
242
  @directives = []
242
243
  else
@@ -5,8 +5,10 @@ module Solargraph
5
5
  class BaseVariable < Base
6
6
  include Solargraph::Source::NodeMethods
7
7
 
8
+ # @return [Parser::AST::Node, nil]
8
9
  attr_reader :assignment
9
10
 
11
+ # @param assignment [Parser::AST::Node, nil]
10
12
  def initialize assignment: nil, **splat
11
13
  super(splat)
12
14
  @assignment = assignment
@@ -41,11 +43,9 @@ module Solargraph
41
43
  return ComplexType::UNDEFINED if @assignment.nil?
42
44
  types = []
43
45
  returns_from(@assignment).each do |node|
44
- chain = Source::NodeChainer.chain(node, filename)
45
- next if chain.links.first.word == name
46
- clip = api_map.clip_at(location.filename, location.range.start)
47
- locals = clip.locals - [self]
48
- result = chain.infer(api_map, closure, locals)
46
+ pos = Solargraph::Position.new(node.loc.expression.last_line, node.loc.expression.last_column)
47
+ clip = api_map.clip_at(location.filename, pos)
48
+ result = clip.infer
49
49
  types.push result unless result.undefined?
50
50
  end
51
51
  return ComplexType::UNDEFINED if types.empty?
@@ -66,6 +66,7 @@ module Solargraph
66
66
 
67
67
  private
68
68
 
69
+ # @return [ComplexType]
69
70
  def generate_complex_type
70
71
  tag = docstring.tag(:type)
71
72
  return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
@@ -26,13 +26,6 @@ module Solargraph
26
26
  closure.is_a?(Pin::Block) ? typify_block_param(api_map) : typify_method_param(api_map)
27
27
  end
28
28
 
29
- def try_merge! pin
30
- return false unless super && closure.nearly?(pin.closure)
31
- @return_type = pin.return_type
32
- reset_conversions
33
- true
34
- end
35
-
36
29
  def documentation
37
30
  tag = param_tag
38
31
  return '' if tag.nil? || tag.text.nil?
@@ -118,7 +111,7 @@ module Solargraph
118
111
  # @param heredoc [YARD::Docstring]
119
112
  # @param api_map [ApiMap]
120
113
  # @param skip [Array]
121
- # @return [ComplexType]
114
+ # @return [Array<YARD::Tags::Tag>]
122
115
  def see_reference heredoc, api_map, skip = []
123
116
  heredoc.ref_tags.each do |ref|
124
117
  next unless ref.tag_name == 'param' && ref.owner
@@ -131,7 +124,7 @@ module Solargraph
131
124
  # @param ref [String]
132
125
  # @param api_map [ApiMap]
133
126
  # @param skip [Array]
134
- # @return [ComplexType]
127
+ # @return [Array<YARD::Tags::Tag>, nil]
135
128
  def resolve_reference ref, api_map, skip
136
129
  return nil if skip.include?(ref)
137
130
  skip.push ref
@@ -140,7 +133,7 @@ module Solargraph
140
133
  path = "#{namespace}#{ref}"
141
134
  else
142
135
  fqns = api_map.qualify(parts.first, namespace)
143
- return ComplexType::UNDEFINED if fqns.nil?
136
+ return nil if fqns.nil?
144
137
  path = fqns + ref[parts.first.length] + parts.last
145
138
  end
146
139
  pins = api_map.get_path_pins(path)
@@ -19,6 +19,7 @@ module Solargraph
19
19
  autoload :Literal, 'solargraph/source/chain/literal'
20
20
  autoload :Head, 'solargraph/source/chain/head'
21
21
  autoload :Or, 'solargraph/source/chain/or'
22
+ autoload :BlockVariable, 'solargraph/source/chain/block_variable'
22
23
 
23
24
  @@inference_stack = []
24
25
  @@inference_depth = 0
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class BlockVariable < Link
7
+ def resolve api_map, name_pin, locals
8
+ Pin::ProxyType.anonymous('Proc')
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -48,7 +48,9 @@ module Solargraph
48
48
  return generate_links(n.children[0]) if n.type == :begin
49
49
  result = []
50
50
  if n.type == :block
51
+ @in_block = true
51
52
  result.concat generate_links(n.children[0])
53
+ @in_block = false
52
54
  elsif n.type == :send
53
55
  if n.children[0].is_a?(Parser::AST::Node)
54
56
  result.concat generate_links(n.children[0])
@@ -56,13 +58,13 @@ module Solargraph
56
58
  n.children[2..-1].each do |c|
57
59
  args.push NodeChainer.chain(c)
58
60
  end
59
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block)
61
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
60
62
  elsif n.children[0].nil?
61
63
  args = []
62
64
  n.children[2..-1].each do |c|
63
65
  args.push NodeChainer.chain(c)
64
66
  end
65
- result.push Chain::Call.new(n.children[1].to_s, args, @in_block)
67
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
66
68
  else
67
69
  raise "No idea what to do with #{n}"
68
70
  end
@@ -92,12 +94,18 @@ module Solargraph
92
94
  result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename)])
93
95
  elsif [:begin, :kwbegin].include?(n.type)
94
96
  result.concat generate_links(n.children[0])
97
+ elsif n.type == :block_pass
98
+ result.push Chain::BlockVariable.new("&#{n.children[0].children[0].to_s}")
95
99
  else
96
100
  lit = infer_literal_node_type(n)
97
101
  result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
98
102
  end
99
103
  result
100
104
  end
105
+
106
+ def block_passed? node
107
+ node.children.last.is_a?(Parser::AST::Node) && node.children.last.type == :block_pass
108
+ end
101
109
  end
102
110
  end
103
111
  end
@@ -122,6 +122,8 @@ module Solargraph
122
122
  signature
123
123
  end
124
124
 
125
+ NIL_NODE = Parser::AST::Node.new(:nil)
126
+
125
127
  # Find all the nodes within the provided node that potentially return a
126
128
  # value.
127
129
  #
@@ -129,24 +131,20 @@ module Solargraph
129
131
  # second child (after the :args node) of a :def node. A simple one-line
130
132
  # method would typically return itself, while a node with conditions
131
133
  # would return the resulting node from each conditional branch. Nodes
132
- # that follow a :return node are assumed to be unreachable. Implicit nil
133
- # values are ignored.
134
- #
135
- # @todo Maybe this method should include implicit nil values in results.
136
- # For example, a bare `return` would return a :nil node instead of an
137
- # empty array.
134
+ # that follow a :return node are assumed to be unreachable. Nil values
135
+ # are converted to nil node types.
138
136
  #
139
- # @param node [AST::Node]
140
- # @return [Array<AST::Node>]
137
+ # @param node [Parser::AST::Node]
138
+ # @return [Array<Parser::AST::Node>]
141
139
  def returns_from node
142
- DeepInference.get_return_nodes(node)
140
+ DeepInference.get_return_nodes(node).map { |n| n || NIL_NODE }
143
141
  end
144
142
 
145
143
  module DeepInference
146
144
  class << self
147
145
  CONDITIONAL = [:if, :unless]
148
146
  REDUCEABLE = [:begin, :kwbegin]
149
- SKIPPABLE = [:def, :defs, :class, :sclass, :module, :block]
147
+ SKIPPABLE = [:def, :defs, :class, :sclass, :module]
150
148
 
151
149
  # @param node [Parser::AST::Node]
152
150
  # @return [Array<Parser::AST::Node>]
@@ -162,7 +160,8 @@ module Solargraph
162
160
  elsif node.type == :return
163
161
  result.concat reduce_to_value_nodes([node.children[0]])
164
162
  elsif node.type == :block
165
- result.concat reduce_to_value_nodes(node.children[0..-2])
163
+ result.concat reduce_to_value_nodes([node.children[0]])
164
+ result.concat get_return_nodes_only(node.children[2])
166
165
  else
167
166
  result.push node
168
167
  end
@@ -174,9 +173,12 @@ module Solargraph
174
173
  def get_return_nodes_from_children parent
175
174
  result = []
176
175
  nodes = parent.children.select{|n| n.is_a?(AST::Node)}
177
- nodes[0..-2].each do |node|
178
- next if SKIPPABLE.include?(node.type)
179
- if node.type == :return
176
+ nodes.each_with_index do |node, idx|
177
+ if node.type == :block
178
+ result.concat get_return_nodes_only(node.children[2])
179
+ elsif SKIPPABLE.include?(node.type)
180
+ next
181
+ elsif node.type == :return
180
182
  result.concat reduce_to_value_nodes([node.children[0]])
181
183
  # Return the result here because the rest of the code is
182
184
  # unreachable
@@ -184,8 +186,8 @@ module Solargraph
184
186
  else
185
187
  result.concat get_return_nodes_only(node)
186
188
  end
189
+ result.concat reduce_to_value_nodes([nodes.last]) if idx == nodes.length - 1
187
190
  end
188
- result.concat reduce_to_value_nodes([nodes.last]) unless nodes.last.nil?
189
191
  result
190
192
  end
191
193
 
@@ -41,6 +41,7 @@ module Solargraph
41
41
  node, parent = source.tree_at(position.line, position.column)[0..2]
42
42
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
43
43
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
44
+ node = Source.parse(fixed_phrase) if node.nil?
44
45
  else
45
46
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
46
47
  # Exception for positions that chain literal nodes in unsynchronized sources
@@ -53,9 +53,9 @@ module Solargraph
53
53
  type = par.typify(api_map)
54
54
  pdefs = ParamDef.from(par.closure)
55
55
  if type.undefined?
56
- if par.return_type.undefined? && !pdefs.any? { |pd| pd.name == par.name && [:restarg, :kwrestarg].include?(pd.type) }
56
+ if par.return_type.undefined? && !pdefs.any? { |pd| pd.name == par.name && [:restarg, :kwrestarg, :blockarg].include?(pd.type) }
57
57
  result.push Problem.new(par.location, "#{par.closure.name} has undefined @param type for #{par.name}")
58
- elsif !pdefs.any? { |pd| [:restarg, :kwrestarg].include?(pd.type) }
58
+ elsif !pdefs.any? { |pd| [:restarg, :kwrestarg, :blockarg].include?(pd.type) }
59
59
  result.push Problem.new(par.location, "#{par.closure.name} has unresolved @param type for #{par.name}")
60
60
  end
61
61
  end
@@ -40,6 +40,7 @@ module Solargraph
40
40
  return :optarg if string.include?('=')
41
41
  return :kwoptarg if string.end_with?(':')
42
42
  return :kwarg if string =~ /^[a-z0-9_]*?:/
43
+ return :blockarg if string.start_with?('&')
43
44
  :arg
44
45
  end
45
46
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.34.3'
4
+ VERSION = '0.35.0'
5
5
  end
@@ -10,7 +10,7 @@ module Solargraph
10
10
  # The maximum number of files that can be added to a workspace.
11
11
  # The workspace's .solargraph.yml can override this value.
12
12
  MAX_FILES = 5000
13
-
13
+
14
14
  # @return [String]
15
15
  attr_reader :directory
16
16
 
@@ -20,24 +20,7 @@ module Solargraph
20
20
  # @param directory [String]
21
21
  def initialize directory = ''
22
22
  @directory = directory
23
- include_globs = ['**/*.rb']
24
- exclude_globs = ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*']
25
- unless @directory.empty?
26
- sfile = File.join(@directory, '.solargraph.yml')
27
- if File.file?(sfile)
28
- @raw_data = YAML.safe_load(File.read(sfile))
29
- include_globs = @raw_data['include'] || include_globs
30
- exclude_globs = @raw_data['exclude'] || []
31
- end
32
- end
33
- @raw_data ||= {}
34
- @raw_data['include'] ||= include_globs
35
- @raw_data['exclude'] ||= exclude_globs
36
- @raw_data['require'] ||= []
37
- @raw_data['domains'] ||= []
38
- @raw_data['reporters'] ||= %w[rubocop require_not_found]
39
- @raw_data['require_paths'] ||= []
40
- @raw_data['max_files'] ||= MAX_FILES
23
+ @raw_data = config_data
41
24
  included
42
25
  excluded
43
26
  end
@@ -110,6 +93,54 @@ module Solargraph
110
93
  end
111
94
 
112
95
  private
96
+
97
+ # @return [String]
98
+ def global_config_path
99
+ ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
100
+ File.join(Dir.home, '.config', 'solargraph', 'config.yml')
101
+ end
102
+
103
+ # @return [String]
104
+ def workspace_config_path
105
+ return '' if @directory.empty?
106
+ File.join(@directory, '.solargraph.yml')
107
+ end
108
+
109
+ # @return [Hash]
110
+ def config_data
111
+ workspace_config = read_config(workspace_config_path)
112
+ global_config = read_config(global_config_path)
113
+
114
+ defaults = default_config
115
+ defaults.merge({'exclude' => []}) unless workspace_config.nil?
116
+
117
+ defaults
118
+ .merge(global_config || {})
119
+ .merge(workspace_config || {})
120
+ end
121
+
122
+ # Read a .solargraph yaml config
123
+ #
124
+ # @param directory [String]
125
+ # @return [Hash]
126
+ def read_config config_path = ''
127
+ return nil if config_path.empty?
128
+ return nil unless File.file?(config_path)
129
+ YAML.safe_load(File.read(config_path))
130
+ end
131
+
132
+ # @return [Hash]
133
+ def default_config
134
+ {
135
+ 'include' => ['**/*.rb'],
136
+ 'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],
137
+ 'require' => [],
138
+ 'domains' => [],
139
+ 'reporters' => %w[rubocop require_not_found],
140
+ 'require_paths' => [],
141
+ 'max_files' => MAX_FILES,
142
+ }
143
+ end
113
144
 
114
145
  # Get an array of files from the provided globs.
115
146
  #
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.34.3
4
+ version: 0.35.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: 2019-07-15 00:00:00.000000000 Z
11
+ date: 2019-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport
@@ -381,6 +381,7 @@ files:
381
381
  - lib/solargraph/shell.rb
382
382
  - lib/solargraph/source.rb
383
383
  - lib/solargraph/source/chain.rb
384
+ - lib/solargraph/source/chain/block_variable.rb
384
385
  - lib/solargraph/source/chain/call.rb
385
386
  - lib/solargraph/source/chain/class_variable.rb
386
387
  - lib/solargraph/source/chain/constant.rb