solargraph 0.28.2 → 0.28.3

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: 99d55308f8ad7a0f73c4432cf08789471b46a60df7db0cc59a4ca8ef6dd9360f
4
- data.tar.gz: 8b81acc2451105bb669fbaa0eb215f27ef6f32306b354683c0c045374317e4f8
3
+ metadata.gz: a5263886b3711a2cc3a6ff8b93c6162002feae2162055999a42d0e571473e47c
4
+ data.tar.gz: e936cac7abedde1efab2c97618c15a0290937211016cb7ae0a71d607b6483e23
5
5
  SHA512:
6
- metadata.gz: 482e84a980ef3385ee1f182c17681bdd97912b84055b017dd5821641a82a240945c1e080bbd11dee0a32df520069318aafef85687a24d801089574fb88154f2f
7
- data.tar.gz: 14cf67e4029a2f1fcc8fdbccfd521f7db6776d010d2f4681c77db56b5f5da0a4ebdc51499ef60c5ff5fcd6fa031ab054f250491b71a2ac4394feef4b8aeaa9c5
6
+ metadata.gz: c8dd13d206f759022ab35d9721672b2a0c1c517a18f9e58cfeec7143eacdd6e8d20ad726cb5539bb2e010b9ec82593a4b164dd5bed4ddcb48e4adde17e226689
7
+ data.tar.gz: b4e88b5cd5f6c5d4495d4562edfd2510651410fe17e6e6b4db33dcee85afbe0ba7110fba5dabd143c76fd04a94e359ad07adae0588ca67ca2a1e445dd421ce67
@@ -46,7 +46,7 @@ module Solargraph
46
46
  # @param source [Source]
47
47
  # @return [self]
48
48
  def map source
49
- catalog Bundle.new(sources: [source])
49
+ catalog Bundle.new(opened: [source])
50
50
  self
51
51
  end
52
52
 
@@ -56,9 +56,6 @@ module Solargraph
56
56
  # @param bundle [Bundle]
57
57
  # @return [self]
58
58
  def catalog bundle
59
- # @todo This can be more efficient. We don't need to remap sources that
60
- # are already here.
61
- # all_sources = (workspace.sources + others).uniq
62
59
  new_map_hash = {}
63
60
  unmerged = false
64
61
  bundle.sources.each do |source|
@@ -88,11 +85,11 @@ module Solargraph
88
85
  pins.concat map.pins
89
86
  reqs.concat map.requires.map(&:name)
90
87
  end
91
- reqs.concat bundle.required
92
- unless bundle.load_paths.empty?
88
+ reqs.concat bundle.workspace.config.required
89
+ unless bundle.workspace.require_paths.empty?
93
90
  reqs.delete_if do |r|
94
91
  result = false
95
- bundle.load_paths.each do |l|
92
+ bundle.workspace.require_paths.each do |l|
96
93
  if new_map_hash.keys.include?(File.join(l, "#{r}.rb"))
97
94
  result = true
98
95
  break
@@ -101,13 +98,13 @@ module Solargraph
101
98
  result
102
99
  end
103
100
  end
104
- bundle.yard_map.change(reqs)
105
- new_store = Store.new(pins + bundle.yard_map.pins)
101
+ yard_map.change(reqs)
102
+ new_store = Store.new(pins + yard_map.pins)
106
103
  @mutex.synchronize {
107
104
  @cache.clear
108
105
  @source_map_hash = new_map_hash
109
106
  @store = new_store
110
- @unresolved_requires = bundle.yard_map.unresolved_requires
107
+ @unresolved_requires = yard_map.unresolved_requires
111
108
  }
112
109
  self
113
110
  end
@@ -137,7 +134,7 @@ module Solargraph
137
134
  # @todo How should this work?
138
135
  api_map = self.new #(Solargraph::Workspace.new(directory))
139
136
  workspace = Solargraph::Workspace.new(directory)
140
- api_map.catalog Bundle.new(sources: workspace.sources)
137
+ api_map.catalog Bundle.new(workspace: workspace)
141
138
  api_map
142
139
  end
143
140
 
@@ -445,6 +442,10 @@ module Solargraph
445
442
 
446
443
  private
447
444
 
445
+ def yard_map
446
+ @yard_map ||= YardMap.new
447
+ end
448
+
448
449
  # A hash of source maps with filename keys.
449
450
  #
450
451
  # @return [Hash{String => SourceMap}]
@@ -1,22 +1,21 @@
1
1
  module Solargraph
2
2
  class Bundle
3
- # @return [Array<Source>]
4
- attr_reader :sources
5
-
6
- # @return [Array<String>]
7
- attr_reader :required
3
+ # @return [Workspace]
4
+ attr_reader :workspace
8
5
 
9
- # @return [Array<String>]
10
- attr_reader :load_paths
6
+ # @return [Array<Source>]
7
+ attr_reader :opened
11
8
 
12
- # @return [YardMap]
13
- attr_reader :yard_map
9
+ # @param workspace [Workspace]
10
+ # @param opened [Array<Source>]
11
+ def initialize workspace: Workspace.new, opened: []
12
+ @workspace = workspace
13
+ @opened = opened
14
+ end
14
15
 
15
- def initialize sources: [], required: [], load_paths: [], yard_map: YardMap.new
16
- @sources = sources
17
- @required = required
18
- @load_paths = load_paths
19
- @yard_map = yard_map
16
+ # @return [Array<Source>]
17
+ def sources
18
+ @sources ||= (opened + workspace.sources).uniq(&:filename)
20
19
  end
21
20
  end
22
21
  end
@@ -15,6 +15,7 @@ module Solargraph
15
15
  #
16
16
  # @param name [String] The name
17
17
  # @param klass [Class<Solargraph::Diagnostics::Base>] The class implementation
18
+ # @return [void]
18
19
  def register name, klass
19
20
  reporter_hash[name] = klass
20
21
  end
@@ -1,5 +1,7 @@
1
1
  module Solargraph
2
2
  module Diagnostics
3
+ # The base class for diagnostics reporters.
4
+ #
3
5
  class Base
4
6
  # Perform a diagnosis on a Source within the context of an ApiMap.
5
7
  # The result is an array of hash objects that conform to the LSP's
@@ -19,23 +19,19 @@ module Solargraph
19
19
  # @param api_map [Solargraph::ApiMap]
20
20
  # @return [Array<Hash>]
21
21
  def diagnose source, api_map
22
- begin
23
- options, paths = generate_options(source.filename, source.code)
24
- runner = RuboCop::Runner.new(options, RuboCop::ConfigStore.new)
25
- result = redirect_stdout{ runner.run(paths) }
26
- make_array JSON.parse(result)
27
- rescue JSON::ParserError
28
- raise DiagnosticsError, 'RuboCop returned invalid data'
29
- end
22
+ options, paths = generate_options(source.filename, source.code)
23
+ runner = RuboCop::Runner.new(options, RuboCop::ConfigStore.new)
24
+ result = redirect_stdout{ runner.run(paths) }
25
+ make_array JSON.parse(result)
26
+ rescue JSON::ParserError
27
+ raise DiagnosticsError, 'RuboCop returned invalid data'
30
28
  end
31
29
 
32
30
  private
33
31
 
34
- # @param workspace [Solargraph::Workspace]
35
32
  # @param filename [String]
36
33
  # @param code [String]
37
34
  # @return [Array]
38
- # def generate_options workspace, filename, code
39
35
  def generate_options filename, code
40
36
  args = ['-f', 'j']
41
37
  rubocop_file = find_rubocop_file(filename)
@@ -46,20 +42,16 @@ module Solargraph
46
42
  [options, paths]
47
43
  end
48
44
 
45
+ # @param filename [String]
46
+ # @return [String, nil]
49
47
  def find_rubocop_file filename
50
- rcfile = nil
51
48
  dir = File.dirname(filename)
52
- while rcfile.nil?
49
+ until File.dirname(dir) == dir
53
50
  here = File.join(dir, '.rubocop.yml')
54
- if File.exist?(here)
55
- rcfile = here
56
- break
57
- else
58
- break if File.dirname(dir) == dir
59
- dir = File.dirname(dir)
60
- end
51
+ return here if File.exist?(here)
52
+ dir = File.dirname(dir)
61
53
  end
62
- rcfile
54
+ nil
63
55
  end
64
56
 
65
57
  # @todo This is a smelly way to redirect output, but the RuboCop specs do the
@@ -136,13 +136,6 @@ module Solargraph
136
136
  diagnoser.schedule uri
137
137
  end
138
138
 
139
- def save params
140
- uri = params['textDocument']['uri']
141
- filename = uri_to_file(uri)
142
- version = params['textDocument']['version']
143
- library.overwrite filename, version
144
- end
145
-
146
139
  # @param uri [String]
147
140
  def diagnose uri
148
141
  begin
@@ -193,7 +186,7 @@ module Solargraph
193
186
  #
194
187
  # @param directory [String]
195
188
  def prepare directory
196
- path = nil
189
+ path = ''
197
190
  path = normalize_separators(directory) unless directory.nil?
198
191
  begin
199
192
  @library = Solargraph::Library.load(path)
@@ -202,7 +195,7 @@ module Solargraph
202
195
  'type' => Solargraph::LanguageServer::MessageTypes::WARNING,
203
196
  'message' => e.message
204
197
  }
205
- @library = Solargraph::Library.load(nil)
198
+ @library = Solargraph::Library.load
206
199
  end
207
200
  diagnoser.start
208
201
  cataloger.start
@@ -565,6 +558,9 @@ module Solargraph
565
558
  },
566
559
  'workspace/symbol' => {
567
560
  workspaceSymbolProvider: true
561
+ },
562
+ 'textDocument/formatting' => {
563
+ formattingProvider: true
568
564
  }
569
565
  }
570
566
  end
@@ -5,11 +5,12 @@ module Solargraph
5
5
  module LanguageServer
6
6
  module Message
7
7
  module CompletionItem
8
+ # completionItem/resolve message handler
9
+ #
8
10
  class Resolve < Base
9
11
  def process
10
12
  pin = host.locate_pin params
11
13
  if pin.nil?
12
- # set_error(Solargraph::LanguageServer::ErrorCodes::INVALID_REQUEST, "Completion item could not be resolved")
13
14
  set_result params
14
15
  else
15
16
  set_result(
@@ -14,10 +14,29 @@ module Solargraph
14
14
  lines = o.lines
15
15
  index = lines.index{|l| l.start_with?('====================')}
16
16
  formatted = lines[index+1..-1].join
17
+ # The response is required to send an explicit range. Text edits
18
+ # with null ranges get ignored. See castwide/vscode-solargraph#83
19
+ if original.end_with?("\n")
20
+ ending = {
21
+ line: original.lines.length,
22
+ character: 0
23
+ }
24
+ else
25
+ ending = {
26
+ line: original.lines.length - 1,
27
+ character: original.lines.last.length
28
+ }
29
+ end
17
30
  set_result(
18
31
  [
19
32
  {
20
- range: nil,
33
+ range: {
34
+ start: {
35
+ line: 0,
36
+ character: 0
37
+ },
38
+ end: ending
39
+ },
21
40
  newText: formatted
22
41
  }
23
42
  ]
@@ -1,11 +1,9 @@
1
- require 'set'
2
-
3
1
  module Solargraph
4
- # A library handles coordination between a Workspace and an ApiMap.
2
+ # A Library handles coordination between a Workspace and an ApiMap.
5
3
  #
6
4
  class Library
7
5
  # @param workspace [Solargraph::Workspace]
8
- def initialize workspace = Solargraph::Workspace.new(nil)
6
+ def initialize workspace = Solargraph::Workspace.new
9
7
  @mutex = Mutex.new
10
8
  @workspace = workspace
11
9
  api_map.catalog bundle
@@ -115,22 +113,6 @@ module Solargraph
115
113
  end
116
114
  end
117
115
 
118
- # @param filename [String]
119
- # @param version [Integer]
120
- # @return [void]
121
- def overwrite filename, version
122
- mutex.synchronize do
123
- source = source_hash[filename]
124
- return if source.nil?
125
- if source.version > version
126
- STDERR.puts "Save out of sync for #{filename} (current #{source.version}, overwrite #{version})" if source.version > version
127
- else
128
- open filename, File.read(filename), version
129
- end
130
- catalog
131
- end
132
- end
133
-
134
116
  # Get completion suggestions at the specified file and location.
135
117
  #
136
118
  # @param filename [String] The file to analyze
@@ -336,7 +318,7 @@ module Solargraph
336
318
  #
337
319
  # @param directory [String] The path to be used for the workspace
338
320
  # @return [Solargraph::Library]
339
- def self.load directory
321
+ def self.load directory = ''
340
322
  Solargraph::Library.new(Solargraph::Workspace.new(directory))
341
323
  end
342
324
 
@@ -358,10 +340,8 @@ module Solargraph
358
340
  # @return [Bundle]
359
341
  def bundle
360
342
  Bundle.new(
361
- sources: (workspace.sources + open_file_hash.values).uniq(&:filename),
362
- required: workspace.config.required,
363
- load_paths: workspace.require_paths,
364
- yard_map: yard_map
343
+ workspace: workspace,
344
+ opened: open_file_hash.values
365
345
  )
366
346
  end
367
347
 
@@ -1,4 +1,6 @@
1
1
  module Solargraph
2
+ # A section of text identified by its filename and range.
3
+ #
2
4
  class Location
3
5
  # @return [String]
4
6
  attr_reader :filename
@@ -13,6 +15,7 @@ module Solargraph
13
15
  @range = range
14
16
  end
15
17
 
18
+ # @return [Hash]
16
19
  def to_hash
17
20
  {
18
21
  filename: filename,
@@ -1,4 +1,6 @@
1
1
  module Solargraph
2
+ # The namespace for pins used in maps.
3
+ #
2
4
  module Pin
3
5
  autoload :Helper, 'solargraph/pin/helper'
4
6
  autoload :Conversions, 'solargraph/pin/conversions'
@@ -2,6 +2,8 @@ require 'reverse_markdown'
2
2
 
3
3
  module Solargraph
4
4
  module Pin
5
+ # The base class for map pins.
6
+ #
5
7
  class Base
6
8
  include Conversions
7
9
  include Documenting
@@ -214,10 +216,10 @@ module Solargraph
214
216
  # @param t2 [YARD::Tags::Tag]
215
217
  # @return [Boolean]
216
218
  def compare_tags t1, t2
217
- t1.class == t2.class and
218
- t1.tag_name == t2.tag_name and
219
- t1.text == t2.text and
220
- t1.name == t2.name and
219
+ t1.class == t2.class &&
220
+ t1.tag_name == t2.tag_name &&
221
+ t1.text == t2.text &&
222
+ t1.name == t2.name &&
221
223
  t1.types == t2.types
222
224
  end
223
225
  end
@@ -9,6 +9,10 @@ module Solargraph
9
9
  params.each do |p|
10
10
  next unless p.name == name
11
11
  found = p
12
+ break
13
+ end
14
+ if found.nil? and !index.nil?
15
+ found = params[index] if params[index] && (params[index].name.nil? || params[index].name.empty?)
12
16
  end
13
17
  @return_complex_type = ComplexType.parse(*found.types) unless found.nil? or found.types.nil?
14
18
  end
@@ -16,6 +20,13 @@ module Solargraph
16
20
  @return_complex_type
17
21
  end
18
22
 
23
+ # The parameter's zero-based location in the block's signature.
24
+ #
25
+ # @return [Integer]
26
+ def index
27
+ block.parameter_names.index(name)
28
+ end
29
+
19
30
  def try_merge! pin
20
31
  return false unless super
21
32
  # @todo This is a little expensive, but it's necessary because
@@ -1,4 +1,6 @@
1
1
  module Solargraph
2
+ # A pair of positions that compose a section of text.
3
+ #
2
4
  class Range
3
5
  # @return [Position]
4
6
  attr_reader :start
@@ -29,9 +31,9 @@ module Solargraph
29
31
  # @param position [Solargraph::Position]
30
32
  # @return [Boolean]
31
33
  def contain? position
32
- return false if position.line < start.line or position.line > ending.line
33
- return false if position.line == start.line and position.character < start.character
34
- return false if position.line == ending.line and position.character > ending.character
34
+ return false if position.line < start.line || position.line > ending.line
35
+ return false if position.line == start.line && position.character < start.character
36
+ return false if position.line == ending.line && position.character > ending.character
35
37
  true
36
38
  end
37
39
 
@@ -40,7 +42,7 @@ module Solargraph
40
42
  # @param position [Position]
41
43
  # @return [Boolean]
42
44
  def include? position
43
- contain?(position) and !(position.line == start.line and position.character == start.character)
45
+ contain?(position) && !(position.line == start.line && position.character == start.character)
44
46
  end
45
47
 
46
48
  # Create a range from a pair of lines and characters.
@@ -54,17 +56,26 @@ module Solargraph
54
56
  Range.new(Position.new(l1, c1), Position.new(l2, c2))
55
57
  end
56
58
 
59
+ # Get a range from a node.
60
+ #
61
+ # @param node [Parser::AST::Node]
62
+ # @return [Range]
57
63
  def self.from_node node
58
64
  from_expr(node.loc.expression)
59
65
  end
60
66
 
67
+ # Get a range from a Parser range, usually found in
68
+ # Parser::AST::Node#location#expression.
69
+ #
70
+ # @param expr [Parser::Source::Range]
71
+ # @return [Range]
61
72
  def self.from_expr expr
62
73
  from_to(expr.line, expr.column, expr.last_line, expr.last_column)
63
74
  end
64
75
 
65
76
  def == other
66
77
  return false unless other.is_a?(Range)
67
- start == other.start and ending == other.ending
78
+ start == other.start && ending == other.ending
68
79
  end
69
80
  end
70
81
  end
@@ -1,8 +1,11 @@
1
- # HACK Fix autoload issue
1
+ # HACK: Fix autoload issue
2
2
  require 'solargraph/source/chain/link'
3
3
 
4
4
  module Solargraph
5
5
  class Source
6
+ # A chain of constants, variables, and method calls for inferring types of
7
+ # values.
8
+ #
6
9
  class Chain
7
10
  autoload :Link, 'solargraph/source/chain/link'
8
11
  autoload :Call, 'solargraph/source/chain/call'
@@ -14,6 +17,10 @@ module Solargraph
14
17
  autoload :Literal, 'solargraph/source/chain/literal'
15
18
  autoload :Head, 'solargraph/source/chain/head'
16
19
 
20
+ # Chain#infer uses the inference stack to avoid recursing into itself.
21
+ # See Chain#active_signature for more information.
22
+ @@inference_stack = []
23
+
17
24
  UNDEFINED_CALL = Chain::Call.new('<undefined>')
18
25
  UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
19
26
 
@@ -37,22 +44,16 @@ module Solargraph
37
44
  # @return [Array<Pin::Base>]
38
45
  def define api_map, name_pin, locals
39
46
  return [] if undefined?
40
- type = ComplexType::UNDEFINED
41
- head = true
42
47
  working_pin = name_pin
43
48
  links[0..-2].each do |link|
44
- pins = link.resolve(api_map, working_pin, head ? locals : [])
45
- head = false
46
- return [] if pins.empty?
47
- type = ComplexType::UNDEFINED
48
- pins.each do |pin|
49
- type = pin.infer(api_map)
50
- break unless type.undefined?
51
- end
49
+ pins = link.resolve(api_map, working_pin, locals)
50
+ # Locals are only used when resolving the first link
51
+ locals = []
52
+ type = infer_first_defined(pins, api_map)
52
53
  return [] if type.undefined?
53
54
  working_pin = Pin::ProxyType.anonymous(type)
54
55
  end
55
- links.last.resolve(api_map, working_pin, head ? locals: [])
56
+ links.last.resolve(api_map, working_pin, locals)
56
57
  end
57
58
 
58
59
  # @param api_map [ApiMap]
@@ -60,27 +61,57 @@ module Solargraph
60
61
  # @param locals [Array<Pin::Base>]
61
62
  # @return [ComplexType]
62
63
  def infer api_map, name_pin, locals
63
- return ComplexType::UNDEFINED if undefined?
64
+ return ComplexType::UNDEFINED if undefined? || @@inference_stack.include?(active_signature(name_pin))
65
+ @@inference_stack.push active_signature(name_pin)
64
66
  type = ComplexType::UNDEFINED
65
67
  pins = define(api_map, name_pin, locals)
66
68
  pins.each do |pin|
67
69
  type = pin.infer(api_map)
68
70
  break unless type.undefined?
69
71
  end
72
+ @@inference_stack.pop
70
73
  type
71
74
  end
72
75
 
76
+ # @return [Boolean]
73
77
  def literal?
74
78
  links.last.is_a?(Chain::Literal)
75
79
  end
76
80
 
81
+ # @return [Boolean]
77
82
  def undefined?
78
83
  links.any?(&:undefined?)
79
84
  end
80
85
 
86
+ # @return [Boolean]
81
87
  def constant?
82
88
  links.last.is_a?(Chain::Constant)
83
89
  end
90
+
91
+ private
92
+
93
+ # Get a signature for this chain that includes the current context
94
+ # where it's being analyzed. Chain#infer uses this value to detect
95
+ # recursive inference into the same chain, e.g., when two variables
96
+ # reference each other in their assignments.
97
+ #
98
+ # @param pin [Pin::Base] The named pin context
99
+ # @return [String]
100
+ def active_signature(pin)
101
+ "#{pin.path}|#{links.map(&:word).join('.')}"
102
+ end
103
+
104
+ # @param pins [Array<Pin::Base>]
105
+ # @param api_map [ApiMap]
106
+ # @return [ComplexType]
107
+ def infer_first_defined pins, api_map
108
+ type = ComplexType::UNDEFINED
109
+ pins.each do |pin|
110
+ type = pin.infer(api_map)
111
+ break unless type.undefined?
112
+ end
113
+ type
114
+ end
84
115
  end
85
116
  end
86
117
  end
@@ -24,7 +24,7 @@ module Solargraph
24
24
  # @param name_pin [Pin::Base]
25
25
  # @return [Array<Pin::Base>]
26
26
  def super_pins api_map, name_pin
27
- pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
27
+ pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
28
28
  pins.reject{|p| p.path == name_pin.path}
29
29
  end
30
30
  end
@@ -1,14 +1,15 @@
1
1
  module Solargraph
2
2
  class Source
3
+ # A factory for generating chains from nodes.
4
+ #
3
5
  class NodeChainer
4
6
  include Source::NodeMethods
5
7
 
8
+ # @param node [Parser::AST::Node]
9
+ # @param filename [String]
6
10
  def initialize node, filename = nil
7
11
  @node = node
8
12
  @filename = filename
9
- # @source = source
10
- # @line = line
11
- # @column = column
12
13
  end
13
14
 
14
15
  # @return [Source::Chain]
@@ -26,7 +27,6 @@ module Solargraph
26
27
  end
27
28
 
28
29
  # @param code [String]
29
- # @param filename [String, nil]
30
30
  # @return [Chain]
31
31
  def load_string(code)
32
32
  node = Source.parse(code.sub(/\.$/, ''))
@@ -47,7 +47,6 @@ module Solargraph
47
47
  # return generate_links(n.children[2] || n.children[0]) if n.type == :block
48
48
  result = []
49
49
  if n.type == :block
50
- # result.concat generate_links(n.children[2])
51
50
  result.concat generate_links(n.children[0])
52
51
  elsif n.type == :send
53
52
  if n.children[0].is_a?(Parser::AST::Node)
@@ -71,12 +70,7 @@ module Solargraph
71
70
  elsif n.type == :zsuper
72
71
  result.push Chain::Head.new('super')
73
72
  elsif n.type == :const
74
- # result.push Chain::Constant.new(unpack_name(n))
75
73
  const = unpack_name(n)
76
- # parts = const.split('::')
77
- # last = parts.pop
78
- # result.push Chain::Constant.new(parts.join('::')) unless parts.empty?
79
- # result.push Chain::Constant.new(last)
80
74
  result.push Chain::Constant.new(const)
81
75
  elsif [:lvar, :lvasgn].include?(n.type)
82
76
  result.push Chain::Call.new(n.children[0].to_s)
@@ -24,11 +24,7 @@ module Solargraph
24
24
  # @param position [Position]
25
25
  def initialize source, position
26
26
  @source = source
27
- # @source.code = source.code
28
27
  @position = position
29
- # @todo Get rid of line/column
30
- @line = position.line
31
- @column = position.column
32
28
  @calculated_literal = false
33
29
  end
34
30
 
@@ -65,16 +61,6 @@ module Solargraph
65
61
  # @return [Position]
66
62
  attr_reader :position
67
63
 
68
- # The zero-based line number of the fragment's location.
69
- #
70
- # @return [Integer]
71
- attr_reader :line
72
-
73
- # The zero-based column number of the fragment's location.
74
- #
75
- # @return [Integer]
76
- attr_reader :column
77
-
78
64
  # @return [Solargraph::Source]
79
65
  attr_reader :source
80
66
 
@@ -105,13 +91,6 @@ module Solargraph
105
91
  end
106
92
  end
107
93
 
108
- # An alias for #column.
109
- #
110
- # @return [Integer]
111
- def character
112
- @column
113
- end
114
-
115
94
  # True if the current offset is inside a string.
116
95
  #
117
96
  # @return [Boolean]
@@ -122,7 +101,7 @@ module Solargraph
122
101
 
123
102
  # @return [Integer]
124
103
  def offset
125
- @offset ||= get_offset(line, column)
104
+ @offset ||= get_offset(position.line, position.column)
126
105
  end
127
106
 
128
107
  # @param line [Integer]
@@ -13,7 +13,7 @@ module Solargraph
13
13
 
14
14
  # @return [Array<Pin::Base>]
15
15
  def define
16
- return [] if cursor.chain.literal?
16
+ return [] if cursor.comment? || cursor.chain.literal?
17
17
  result = cursor.chain.define(api_map, context_pin, locals)
18
18
  result.concat(source_map.pins.select{ |p| p.location.range.start.line == cursor.position.line }) if result.empty?
19
19
  result
@@ -297,6 +297,15 @@ module Solargraph
297
297
  pins.push Solargraph::Pin::Attribute.new(get_node_location(c), pin.namespace, c.children[0].children[0].to_s, comments_for(c) || pin.comments, pin.access, pin.scope, pin.visibility)
298
298
  end
299
299
  end
300
+ elsif c.type == :send && c.children[1] == :alias_method && c.children[2] && c.children[2] && c.children[2].type == :sym && c.children[3] && c.children[3].type == :sym
301
+ pin = pins.select{|p| p.name == c.children[3].children[0].to_s && p.namespace == fqn && p.scope == scope}.first
302
+ unless pin.nil?
303
+ if pin.is_a?(Solargraph::Pin::Method)
304
+ pins.push Solargraph::Pin::Method.new(get_node_location(c), pin.namespace, c.children[2].children[0].to_s, comments_for(c) || pin.comments, pin.scope, pin.visibility, pin.parameters)
305
+ elsif pin.is_a?(Solargraph::Pin::Attribute)
306
+ pins.push Solargraph::Pin::Attribute.new(get_node_location(c), pin.namespace, c.children[2].children[0].to_s, comments_for(c) || pin.comments, pin.access, pin.scope, pin.visibility)
307
+ end
308
+ end
300
309
  elsif c.type == :sclass && c.children[0].type == :self
301
310
  process c, tree, :public, :class, fqn || '', stack
302
311
  next
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.28.2'
2
+ VERSION = '0.28.3'
3
3
  end
@@ -10,19 +10,15 @@ module Solargraph
10
10
  attr_reader :directory
11
11
 
12
12
  # @param directory [String]
13
- def initialize directory = nil, config = nil
14
- # @todo Convert to an absolute path?
13
+ def initialize directory = '', config = nil
15
14
  @directory = directory
16
- @directory = nil if @directory == ''
17
15
  @config = config
18
16
  load_sources
19
17
  end
20
18
 
21
- # @param reload [Boolean] Force a reload of the config file
22
19
  # @return [Solargraph::Workspace::Config]
23
- def config reload = false
24
- @config = Solargraph::Workspace::Config.new(directory) if @config.nil? or reload
25
- @config
20
+ def config
21
+ @config ||= Solargraph::Workspace::Config.new(directory)
26
22
  end
27
23
 
28
24
  # Merge the source. A merge will update the existing source for the file
@@ -32,7 +28,11 @@ module Solargraph
32
28
  # @param source [Solargraph::Source]
33
29
  # @return [Boolean] True if the source was added to the workspace
34
30
  def merge source
35
- return false unless config(true).calculated.include?(source.filename)
31
+ unless source_hash.has_key?(source.filename)
32
+ # Reload the config to determine if a new source should be included
33
+ @config = Solargraph::Workspace::Config.new(directory)
34
+ return false unless config.calculated.include?(source.filename)
35
+ end
36
36
  source_hash[source.filename] = source
37
37
  true
38
38
  end
@@ -42,7 +42,9 @@ module Solargraph
42
42
  # @param filename [String]
43
43
  # @return [Boolean]
44
44
  def would_merge? filename
45
- Solargraph::Workspace::Config.new(directory).calculated.include?(filename)
45
+ return true if source_hash.include?(filename)
46
+ @config = Solargraph::Workspace::Config.new(directory)
47
+ config.calculated.include?(filename)
46
48
  end
47
49
 
48
50
  # Remove a source from the workspace. The source will not be removed if
@@ -51,7 +53,7 @@ module Solargraph
51
53
  # @param filename [String]
52
54
  # @return [Boolean] True if the source was removed from the workspace
53
55
  def remove filename
54
- return false if config(true).calculated.include?(filename)
56
+ return false unless source_hash.has_key?(filename)
55
57
  source_hash.delete filename
56
58
  true
57
59
  end
@@ -107,7 +109,7 @@ module Solargraph
107
109
  #
108
110
  # @return [Array<String>]
109
111
  def gemspecs
110
- return [] if directory.nil?
112
+ return [] if directory.empty?
111
113
  @gemspecs ||= Dir[File.join(directory, '**/*.gemspec')]
112
114
  end
113
115
 
@@ -128,7 +130,7 @@ module Solargraph
128
130
 
129
131
  def load_sources
130
132
  source_hash.clear
131
- unless directory.nil?
133
+ unless directory.empty?
132
134
  size = config.calculated.length
133
135
  raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files
134
136
  config.calculated.each do |filename|
@@ -138,11 +140,14 @@ module Solargraph
138
140
  end
139
141
 
140
142
  def generate_require_paths
141
- return [] if directory.nil?
142
- return configured_require_paths unless gemspec?
143
+ return configured_require_paths if directory.empty? || !gemspec?
143
144
  result = []
144
145
  gemspecs.each do |file|
145
- spec = Gem::Specification.load(file)
146
+ # @todo Evaluating gemspec files violates the goal of not running
147
+ # workspace code, but this is how Gem::Specification.load does it
148
+ # anyway.
149
+ spec = eval(File.read(file), binding, file)
150
+ next unless Gem::Specification === spec
146
151
  base = File.dirname(file)
147
152
  result.concat spec.require_paths.map{ |path| File.join(base, path) } unless spec.nil?
148
153
  end
@@ -152,6 +157,7 @@ module Solargraph
152
157
  end
153
158
 
154
159
  def configured_require_paths
160
+ return ['lib'] if directory.empty?
155
161
  return [File.join(directory, 'lib')] if config.require_paths.empty?
156
162
  config.require_paths.map{|p| File.join(directory, p)}
157
163
  end
@@ -10,18 +10,18 @@ module Solargraph
10
10
  MAX_FILES = 5000
11
11
 
12
12
  # @return [String]
13
- attr_reader :workspace
13
+ attr_reader :directory
14
14
 
15
15
  # @return [Hash]
16
16
  attr_reader :raw_data
17
17
 
18
18
  # @param workspace [String]
19
- def initialize workspace = nil
20
- @workspace = workspace
19
+ def initialize directory = ''
20
+ @directory = directory
21
21
  include_globs = ['**/*.rb']
22
22
  exclude_globs = ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*']
23
- unless @workspace.nil?
24
- sfile = File.join(@workspace, '.solargraph.yml')
23
+ unless @directory.empty?
24
+ sfile = File.join(@directory, '.solargraph.yml')
25
25
  if File.file?(sfile)
26
26
  @raw_data = YAML.safe_load(File.read(sfile))
27
27
  include_globs = @raw_data['include'] || include_globs
@@ -45,7 +45,7 @@ module Solargraph
45
45
  #
46
46
  # @return [Array<String>]
47
47
  def included
48
- return [] if workspace.nil?
48
+ return [] if directory.empty?
49
49
  @included ||= process_globs(@raw_data['include'])
50
50
  end
51
51
 
@@ -53,7 +53,7 @@ module Solargraph
53
53
  #
54
54
  # @return [Array<String>]
55
55
  def excluded
56
- return [] if workspace.nil?
56
+ return [] if directory.empty?
57
57
  @excluded ||= process_exclusions(@raw_data['exclude'])
58
58
  end
59
59
 
@@ -117,7 +117,7 @@ module Solargraph
117
117
  def process_globs globs
118
118
  result = []
119
119
  globs.each do |glob|
120
- result.concat Dir[File.join workspace, glob].map{ |f| f.gsub(/\\/, '/') }
120
+ result.concat Dir[File.join directory, glob].map{ |f| f.gsub(/\\/, '/') }
121
121
  end
122
122
  result
123
123
  end
@@ -130,7 +130,7 @@ module Solargraph
130
130
  def process_exclusions globs
131
131
  remainder = globs.select do |glob|
132
132
  if glob_is_directory?(glob)
133
- exdir = File.join(workspace, glob_to_directory(glob))
133
+ exdir = File.join(directory, glob_to_directory(glob))
134
134
  included.delete_if { |file| file.start_with?(exdir) }
135
135
  false
136
136
  else
@@ -24,7 +24,6 @@ module Solargraph
24
24
  attr_reader :required
25
25
 
26
26
  # @param required [Array<String>]
27
- # @param workspace [Solargraph::Workspace, nil]
28
27
  def initialize(required: [])
29
28
  # HACK: YardMap needs its own copy of this array
30
29
  @required = required.clone
@@ -65,17 +64,15 @@ module Solargraph
65
64
  # @param y [String]
66
65
  # @return [YARD::Registry]
67
66
  def load_yardoc y
68
- begin
69
- if y.kind_of?(Array)
70
- YARD::Registry.load y, true
71
- else
72
- YARD::Registry.load! y
73
- end
74
- rescue Exception => e
75
- STDERR.puts "Error loading yardoc '#{y}' #{e.class} #{e.message}"
76
- yardocs.delete y
77
- nil
67
+ if y.kind_of?(Array)
68
+ YARD::Registry.load y, true
69
+ else
70
+ YARD::Registry.load! y
78
71
  end
72
+ rescue Exception => e
73
+ STDERR.puts "Error loading yardoc '#{y}' #{e.class} #{e.message}"
74
+ yardocs.delete y
75
+ nil
79
76
  end
80
77
 
81
78
  # @return [Array<Solargraph::Pin::Base>]
@@ -254,6 +251,8 @@ module Solargraph
254
251
  result
255
252
  end
256
253
 
254
+ # @param y [String, nil]
255
+ # @return [Array<Pin::Base>]
257
256
  def process_yardoc y
258
257
  return [] if y.nil?
259
258
  size = Dir.glob(File.join(y, '**', '*'))
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.28.2
4
+ version: 0.28.3
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-10-03 00:00:00.000000000 Z
11
+ date: 2018-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser