solargraph 0.28.2 → 0.28.3

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
  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