solargraph 0.44.1 → 0.47.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +41 -0
  3. data/CHANGELOG.md +46 -0
  4. data/README.md +10 -2
  5. data/SPONSORS.md +3 -1
  6. data/lib/solargraph/api_map.rb +27 -22
  7. data/lib/solargraph/complex_type.rb +6 -2
  8. data/lib/solargraph/convention/rspec.rb +13 -4
  9. data/lib/solargraph/diagnostics/require_not_found.rb +16 -0
  10. data/lib/solargraph/diagnostics/rubocop.rb +1 -1
  11. data/lib/solargraph/language_server/message/text_document/hover.rb +16 -4
  12. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +1 -1
  13. data/lib/solargraph/language_server/uri_helpers.rb +1 -1
  14. data/lib/solargraph/parser/legacy/class_methods.rb +9 -8
  15. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +13 -17
  16. data/lib/solargraph/parser/rubyvm/class_methods.rb +2 -13
  17. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +13 -17
  18. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -1
  19. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +2 -2
  20. data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
  21. data/lib/solargraph/pin/block.rb +2 -1
  22. data/lib/solargraph/pin/local_variable.rb +1 -1
  23. data/lib/solargraph/pin/namespace.rb +2 -2
  24. data/lib/solargraph/pin/parameter.rb +3 -8
  25. data/lib/solargraph/pin/search.rb +56 -0
  26. data/lib/solargraph/pin.rb +1 -0
  27. data/lib/solargraph/range.rb +1 -1
  28. data/lib/solargraph/source.rb +1 -1
  29. data/lib/solargraph/source_map/mapper.rb +29 -2
  30. data/lib/solargraph/source_map.rb +1 -10
  31. data/lib/solargraph/type_checker/checks.rb +13 -0
  32. data/lib/solargraph/type_checker.rb +41 -8
  33. data/lib/solargraph/version.rb +1 -1
  34. data/lib/solargraph/workspace.rb +1 -0
  35. data/lib/solargraph/yard_map/core_fills.rb +7 -2
  36. data/lib/solargraph/yard_map.rb +32 -15
  37. data/lib/solargraph.rb +2 -2
  38. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 346926f891270e103d6c7170fe5897587c1d5da45ea33b2a7f4238914b38b236
4
- data.tar.gz: 451b09bf70dc9d760ebfdeb726821e6e653f196bd867da8c7638888803e33a72
3
+ metadata.gz: 9d35030ae56f6aaff108a24e4fb06713f911ba4366feb2223b24ad0ea4568522
4
+ data.tar.gz: a9eeaee16171bc762922ac55d10c61d53bcfe6ef1df0b20623c81e0978a80c7d
5
5
  SHA512:
6
- metadata.gz: 624d1de49ef2762477d7a413adf282a058143a71689ea8cdfcc91177db94c765b997fca00fefd8d0d4915e44e6cd4ae1867297671611ba6d119d610116c5b80a
7
- data.tar.gz: 9f146a371e075407cb8be7b96de08ff24583cf18eb1a29310c1a711c1bd347715d07b0ff6603e9a98b71be7406148e17c907abdcf3bd1a2aba58bd5aeff14685
6
+ metadata.gz: 0b13ae6284def50f72c9aaed3cad6f89e879306dc8421b1c13f622e18181e6d9aaecf4f57ffa56601a00c92066557bb798d3e8ee6a397920ff0072f909e05463
7
+ data.tar.gz: 9a0366309ebe9a4a784c2933a8452e2084c376ff9aa3cd6c3bf555f4d6ce046f11245679c688bef43c6c1e67d94b70afb4250149c9b01b80fc525b80a80b6486
@@ -0,0 +1,41 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with rspec.
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: RSpec
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.4', '2.5', '2.6', '2.7', '3.0']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ # uses: ruby/setup-ruby@v1
33
+ uses: ruby/setup-ruby@2b019609e2b0f1ea1a2bc8ca11cb82ab46ada124
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: false
37
+ - run: bundle install
38
+ - name: Set up yardocs
39
+ run: bundle exec yard gems
40
+ - name: Run tests
41
+ run: bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,49 @@
1
+ ## 0.47.2 - September 30, 2022
2
+ - Fix complex type inference (#578)
3
+ - Off-by-one diagnostic (#595)
4
+
5
+ ## 0.47.1 - September 27, 2022
6
+ - Remove debug code from release (#600)
7
+
8
+ ## 0.47.0 - September 25, 2022
9
+ - Completion candidates for union types (#507)
10
+ - Nullify Hover object instead of contents value (#583)
11
+ - Mapping workspace stuck in 0 (#587)
12
+ - Fix parsing of nested subtypes (#589)
13
+ - Update YARD tags on Pin::Block methods (#588)
14
+ - @!visibility directive support (#566)
15
+
16
+ ## 0.46.0 - August 22, 2022
17
+ - Ignore typecheck errors with @sg-ignore tag (#419)
18
+ - Strict checks report undefined method calls on variables (#553)
19
+ - Infer type from method arguments (#554)
20
+ - Return nil value for empty hover contents (#543)
21
+
22
+ ## 0.45.0 - May 23, 2022
23
+ - Basic support for RSpec #describe and #it
24
+ - fix: domain can complete private method (#490)
25
+ - Update README.md (#533)
26
+ - Doc: update readme.md for add solargraph support (#536)
27
+ - Process DASGN node in Ruby 3
28
+ - File.open core fill
29
+ - replace with_unbundled_env with with_original_env (#489)
30
+ - Require specific version of gem (#509)
31
+ - Support URIs prefixed with single slashed file scheme (#529)
32
+ - Fix typo in README.md (#549)
33
+ - details on config behavior (#556)
34
+ - Consider overloads in arity checks
35
+ - ENV core fill for Hash-like methods (#537)
36
+ - Fix string ranges with substitutions (#463)
37
+
38
+ ## 0.44.3 - January 22, 2022
39
+ - TypeChecker validates aliased namespaces (#497)
40
+ - Always use reference YARD tags when resolving param types (#515) (#516)
41
+ - Skip method aliases in strict type checking
42
+
43
+ ## 0.44.2 - November 23, 2021
44
+ - Scope local variables in class_eval blocks (#503)
45
+ - Fix invalid UTF-8 in node comments (#504)
46
+
1
47
  ## 0.44.1 - November 18, 2021
2
48
  - Chain nil safety navigation operator (#420)
3
49
  - Update closure and context for class_eval receiver (#487)
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Solargraph
2
2
 
3
+ [![RSpec](https://github.com/castwide/solargraph/actions/workflows/rspec.yml/badge.svg)](https://github.com/castwide/solargraph/actions/workflows/rspec.yml)
4
+
3
5
  ## A Ruby Language Server
4
6
 
5
7
  Solargraph provides a comprehensive suite of tools for Ruby programming: intellisense, diagnostics, inline documentation, and type checking.
@@ -31,7 +33,9 @@ Plug-ins and extensions are available for the following editors:
31
33
  * GitHub: https://github.com/castwide/atom-solargraph
32
34
 
33
35
  * **Vim**
34
- * GitHub: https://github.com/autozimu/LanguageClient-neovim
36
+ * GitHub: `LanguageClient-neovim`, https://github.com/autozimu/LanguageClient-neovim
37
+ * GitHub: `coc`, https://github.com/neoclide/coc-solargraph
38
+ * GitHub: `Vim-EasyComplete`, https://github.com/jayli/vim-easycomplete
35
39
 
36
40
  * **Emacs**
37
41
  * GitHub: `eglot.el`, https://github.com/joaotavora/eglot
@@ -41,13 +45,17 @@ Plug-ins and extensions are available for the following editors:
41
45
  * Plugin: https://marketplace.eclipse.org/content/ruby-solargraph
42
46
  * GitHub: https://github.com/PyvesB/eclipse-solargraph
43
47
 
48
+ ### Configuration
49
+
50
+ Solargraph's behavior can be controlled via optional [configuration](https://solargraph.org/guides/configuration) files. The highest priority file is a `.solargraph.yml` file at the root of the project. If not present, any global configuration at `~/.config/solargraph/config.yml` will apply. The path to the global configuration can be overridden with the `SOLARGRAPH_GLOBAL_CONFIG` environment variable.
51
+
44
52
  ### Gem Support
45
53
 
46
54
  Solargraph is capable of providing code completion and documentation for gems that have YARD documentation. You can make sure your gems are documented by running `yard gems` from the command line. (YARD is included as one of Solargraph's gem dependencies. The first time you run it might take a while if you have a lot of gems installed).
47
55
 
48
56
  When editing code, a `require` call that references a gem will pull the documentation into the code maps and include the gem's API in code completion and intellisense.
49
57
 
50
- If your project automatically requires bundled gems (e.g., `require 'bundler/require'`), Solargraph will add all of the Gemfile's default dependecies to the map.
58
+ If your project automatically requires bundled gems (e.g., `require 'bundler/require'`), Solargraph will add all of the Gemfile's default dependencies to the map.
51
59
 
52
60
  ### Type Checking
53
61
 
data/SPONSORS.md CHANGED
@@ -10,6 +10,8 @@ The following people and organizations provide funding or other resources. [Beco
10
10
 
11
11
  ## Named Sponsors
12
12
 
13
- - Emily Strickland
14
13
  - Tom de Grunt
15
14
  - Akira Yamada
15
+ - Erlend Finvåg
16
+ - Matt Massicotte
17
+ - Oscar Rivas
@@ -21,6 +21,9 @@ module Solargraph
21
21
  # @return [Array<String>]
22
22
  attr_reader :unresolved_requires
23
23
 
24
+ # @return [Array<String>]
25
+ attr_reader :missing_docs
26
+
24
27
  # @param pins [Array<Solargraph::Pin::Base>]
25
28
  def initialize pins: []
26
29
  @source_map_hash = {}
@@ -68,6 +71,7 @@ module Solargraph
68
71
  yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
69
72
  @store = Store.new(yard_map.pins + implicit.pins + pins)
70
73
  @unresolved_requires = yard_map.unresolved_requires
74
+ @missing_docs = yard_map.missing_docs
71
75
  @rebindable_method_names = nil
72
76
  store.block_pins.each { |blk| blk.rebind(self) }
73
77
  self
@@ -255,7 +259,7 @@ module Solargraph
255
259
  implicit.domains.each do |domain|
256
260
  type = ComplexType.try_parse(domain)
257
261
  next if type.undefined?
258
- result.concat inner_get_methods(type.name, type.scope, [:public], deep, skip)
262
+ result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
259
263
  end
260
264
  result.concat inner_get_methods(fqns, :class, visibility, deep, skip)
261
265
  result.concat inner_get_methods(fqns, :instance, visibility, deep, skip)
@@ -281,33 +285,33 @@ module Solargraph
281
285
  # type = Solargraph::ComplexType.parse('String')
282
286
  # api_map.get_complex_type_methods(type)
283
287
  #
284
- # @param type [Solargraph::ComplexType] The complex type of the namespace
288
+ # @param complex_type [Solargraph::ComplexType] The complex type of the namespace
285
289
  # @param context [String] The context from which the type is referenced
286
290
  # @param internal [Boolean] True to include private methods
287
291
  # @return [Array<Solargraph::Pin::Base>]
288
- def get_complex_type_methods type, context = '', internal = false
292
+ def get_complex_type_methods complex_type, context = '', internal = false
289
293
  # This method does not qualify the complex type's namespace because
290
294
  # it can cause conflicts between similar names, e.g., `Foo` vs.
291
295
  # `Other::Foo`. It still takes a context argument to determine whether
292
296
  # protected and private methods are visible.
293
- return [] if type.undefined? || type.void?
294
- result = []
295
- if type.duck_type?
296
- type.select(&:duck_type?).each do |t|
297
- result.push Pin::DuckMethod.new(name: t.tag[1..-1])
298
- end
299
- result.concat get_methods('Object')
300
- else
301
- unless type.nil? || type.name == 'void'
302
- visibility = [:public]
303
- if type.namespace == context || super_and_sub?(type.namespace, context)
304
- visibility.push :protected
305
- visibility.push :private if internal
297
+ return [] if complex_type.undefined? || complex_type.void?
298
+ result = Set.new
299
+ complex_type.each do |type|
300
+ if type.duck_type?
301
+ result.add Pin::DuckMethod.new(name: type.to_s[1..-1])
302
+ result.merge get_methods('Object')
303
+ else
304
+ unless type.nil? || type.name == 'void'
305
+ visibility = [:public]
306
+ if type.namespace == context || super_and_sub?(type.namespace, context)
307
+ visibility.push :protected
308
+ visibility.push :private if internal
309
+ end
310
+ result.merge get_methods(type.namespace, scope: type.scope, visibility: visibility)
306
311
  end
307
- result.concat get_methods(type.namespace, scope: type.scope, visibility: visibility)
308
312
  end
309
313
  end
310
- result
314
+ result.to_a
311
315
  end
312
316
 
313
317
  # Get a stack of method pins for a method name in a namespace. The order
@@ -383,9 +387,10 @@ module Solargraph
383
387
  # @param query [String]
384
388
  # @return [Array<Pin::Base>]
385
389
  def query_symbols query
386
- result = []
387
- source_map_hash.each_value { |s| result.concat s.query_symbols(query) }
388
- result
390
+ Pin::Search.new(
391
+ source_map_hash.values.flat_map(&:document_symbols),
392
+ query
393
+ ).results
389
394
  end
390
395
 
391
396
  # @param location [Solargraph::Location]
@@ -525,7 +530,7 @@ module Solargraph
525
530
  end
526
531
  store.domains(fqns).each do |d|
527
532
  dt = ComplexType.try_parse(d)
528
- result.concat inner_get_methods(dt.namespace, dt.scope, [:public], deep, skip)
533
+ result.concat inner_get_methods(dt.namespace, dt.scope, visibility, deep, skip)
529
534
  end
530
535
  end
531
536
  result
@@ -74,6 +74,10 @@ module Solargraph
74
74
  @items.all? &block
75
75
  end
76
76
 
77
+ def any? &block
78
+ @items.any? &block
79
+ end
80
+
77
81
  def selfy?
78
82
  @items.any?(&:selfy?)
79
83
  end
@@ -154,9 +158,9 @@ module Solargraph
154
158
  subtype_string.clear
155
159
  next
156
160
  else
161
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
157
162
  point_stack -= 1
158
- subtype_string += char if point_stack == 0
159
- raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack < 0
163
+ subtype_string += char
160
164
  end
161
165
  next
162
166
  elsif char == '{'
@@ -8,14 +8,23 @@ module Solargraph
8
8
  @environ ||= Environ.new(
9
9
  requires: ['rspec'],
10
10
  domains: ['RSpec::Matchers', 'RSpec::ExpectationGroups'],
11
- # This override is necessary due to an erroneous @return tag in
12
- # rspec's YARD documentation.
13
- # @todo The return types have been fixed (https://github.com/rspec/rspec-expectations/pull/1121)
14
11
  pins: [
12
+ # This override is necessary due to an erroneous @return tag in
13
+ # rspec's YARD documentation.
14
+ # @todo The return types have been fixed (https://github.com/rspec/rspec-expectations/pull/1121)
15
15
  Solargraph::Pin::Reference::Override.method_return('RSpec::Matchers#expect', 'RSpec::Expectations::ExpectationTarget')
16
- ]
16
+ ].concat(extras)
17
17
  )
18
18
  end
19
+
20
+ private
21
+
22
+ def extras
23
+ @@extras ||= SourceMap.load_string(%(
24
+ def describe(*args); end
25
+ def it(*args); end
26
+ )).pins
27
+ end
19
28
  end
20
29
  end
21
30
  end
@@ -12,6 +12,10 @@ module Solargraph
12
12
  refs = {}
13
13
  map = api_map.source_map(source.filename)
14
14
  map.requires.each { |ref| refs[ref.name] = ref }
15
+ api_map.missing_docs.each do |r|
16
+ next unless refs.key?(r)
17
+ result.push docs_error(r, refs[r].location)
18
+ end
15
19
  api_map.unresolved_requires.each do |r|
16
20
  next unless refs.key?(r)
17
21
  result.push require_error(r, refs[r].location)
@@ -21,6 +25,18 @@ module Solargraph
21
25
 
22
26
  private
23
27
 
28
+ # @param path [String]
29
+ # @param location [Location]
30
+ # @return [Hash]
31
+ def docs_error path, location
32
+ {
33
+ range: location.range.to_hash,
34
+ severity: Diagnostics::Severities::WARNING,
35
+ source: 'RequireNotFound',
36
+ message: "YARD docs not found for #{path}"
37
+ }
38
+ end
39
+
24
40
  # @param path [String]
25
41
  # @param location [Location]
26
42
  # @return [Hash]
@@ -89,7 +89,7 @@ module Solargraph
89
89
  Position.new(off['location']['start_line'], 0)
90
90
  else
91
91
  Position.new(
92
- off['location']['start_line'] - 1, off['location']['last_column']
92
+ off['location']['start_line'] - 1, off['location']['last_column'] - 1
93
93
  )
94
94
  end
95
95
  end
@@ -27,16 +27,28 @@ module Solargraph
27
27
  last_link = this_link unless this_link.nil?
28
28
  end
29
29
  set_result(
30
- contents: {
31
- kind: 'markdown',
32
- value: contents.join("\n\n")
33
- }
30
+ contents_or_nil(contents)
34
31
  )
35
32
  rescue FileNotFoundError => e
36
33
  Logging.logger.warn "[#{e.class}] #{e.message}"
37
34
  Logging.logger.warn e.backtrace.join("\n")
38
35
  set_result nil
39
36
  end
37
+
38
+ private
39
+
40
+ def contents_or_nil contents
41
+ stripped = contents
42
+ .map(&:strip)
43
+ .reject { |c| c.empty? }
44
+ return nil if stripped.empty?
45
+ {
46
+ contents: {
47
+ kind: 'markdown',
48
+ value: stripped.join("\n\n")
49
+ }
50
+ }
51
+ end
40
52
  end
41
53
  end
42
54
  end
@@ -8,7 +8,7 @@ class Solargraph::LanguageServer::Message::Workspace::WorkspaceSymbol < Solargra
8
8
  info = pins.map do |pin|
9
9
  uri = file_to_uri(pin.location.filename)
10
10
  {
11
- name: pin.name,
11
+ name: pin.path,
12
12
  containerName: pin.namespace,
13
13
  kind: pin.symbol_kind,
14
14
  location: {
@@ -14,7 +14,7 @@ module Solargraph
14
14
  # @param uri [String]
15
15
  # @return [String]
16
16
  def uri_to_file uri
17
- decode(uri).sub(/^file\:\/\//, '').sub(/^\/([a-z]\:)/i, '\1')
17
+ decode(uri).sub(/^file\:(?:\/\/)?/, '').sub(/^\/([a-z]\:)/i, '\1')
18
18
  end
19
19
 
20
20
  # Convert a file path to a URI.
@@ -48,10 +48,16 @@ module Solargraph
48
48
  end
49
49
 
50
50
  def references source, name
51
+ if name.end_with?("=")
52
+ reg = /#{Regexp.escape name[0..-2]}\s*=/
53
+ extract_offset = ->(code, offset) { reg.match(code, offset).offset(0) }
54
+ else
55
+ extract_offset = ->(code, offset) { [soff = code.index(name, offset), soff + name.length] }
56
+ end
51
57
  inner_node_references(name, source.node).map do |n|
52
- offset = Position.to_offset(source.code, NodeMethods.get_node_start_position(n))
53
- soff = source.code.index(name, offset)
54
- eoff = soff + name.length
58
+ rng = Range.from_node(n)
59
+ offset = Position.to_offset(source.code, rng.start)
60
+ soff, eoff = extract_offset[source.code, offset]
55
61
  Location.new(
56
62
  source.filename,
57
63
  Range.new(
@@ -109,16 +115,11 @@ module Solargraph
109
115
  result = []
110
116
  if node.type == :str
111
117
  result.push Range.from_node(node)
112
- elsif node.type == :dstr
113
- here = Range.from_node(node)
114
- there = Range.from_node(node.children[1])
115
- result.push Range.new(here.start, there.start)
116
118
  end
117
119
  node.children.each do |child|
118
120
  result.concat string_ranges(child)
119
121
  end
120
122
  if node.type == :dstr && node.children.last.nil?
121
- # result.push Range.new(result.last.ending, result.last.ending)
122
123
  last = node.children[-2]
123
124
  unless last.nil?
124
125
  rng = Range.from_node(last)
@@ -8,17 +8,24 @@ module Solargraph
8
8
  include Legacy::NodeMethods
9
9
 
10
10
  def process
11
- if other_class_eval?
12
- other_class = Solargraph::Pin::Namespace.new(
11
+ location = get_node_location(node)
12
+ parent = if other_class_eval?
13
+ Solargraph::Pin::Namespace.new(
14
+ location: location,
13
15
  type: :class,
14
16
  name: unpack_name(node.children[0].children[0])
15
17
  )
16
- make_block_in other_class.context
17
- process_children region.update(closure: other_class)
18
18
  else
19
- make_block_in nil
20
- process_children region.update(closure: pins.last)
19
+ region.closure
21
20
  end
21
+ pins.push Solargraph::Pin::Block.new(
22
+ location: location,
23
+ closure: parent,
24
+ receiver: node.children[0],
25
+ comments: comments_for(node),
26
+ scope: region.scope || region.closure.context.scope
27
+ )
28
+ process_children region.update(closure: pins.last)
22
29
  end
23
30
 
24
31
  private
@@ -28,17 +35,6 @@ module Solargraph
28
35
  node.children[0].children[1] == :class_eval &&
29
36
  [:cbase, :const].include?(node.children[0].children[0]&.type)
30
37
  end
31
-
32
- def make_block_in context
33
- pins.push Solargraph::Pin::Block.new(
34
- location: get_node_location(node),
35
- context: context,
36
- closure: region.closure,
37
- receiver: node.children[0],
38
- comments: comments_for(node),
39
- scope: region.scope || region.closure.context.scope
40
- )
41
- end
42
38
  end
43
39
  end
44
40
  end
@@ -29,16 +29,6 @@ module Solargraph
29
29
  NodeProcessor.process(source.node, Region.new(source: source))
30
30
  end
31
31
 
32
- # def returns_from node
33
- # return [] unless Parser.is_ast_node?(node)
34
- # if node.type == :SCOPE
35
- # # node.children.select { |n| n.is_a?(RubyVM::AbstractSyntaxTree::Node) }.map { |n| DeepInference.get_return_nodes(n) }.flatten
36
- # DeepInference.get_return_nodes(node.children[2])
37
- # else
38
- # DeepInference.get_return_nodes(node)
39
- # end
40
- # end
41
-
42
32
  def references source, name
43
33
  if name.end_with?("=")
44
34
  reg = /#{Regexp.escape name[0..-2]}\s*=/
@@ -97,7 +87,7 @@ module Solargraph
97
87
  end
98
88
 
99
89
  def infer_literal_node_type node
100
- # NodeMethods.infer_literal_node_type node
90
+ NodeMethods.infer_literal_node_type node
101
91
  end
102
92
 
103
93
  def version
@@ -133,13 +123,12 @@ module Solargraph
133
123
  elsif node.type == :DSTR
134
124
  here = Range.from_node(node)
135
125
  there = Range.from_node(node.children[1])
136
- result.push Range.new(here.start, there.start)
126
+ result.push Range.new(here.start, there&.start || here.ending)
137
127
  end
138
128
  node.children.each do |child|
139
129
  result.concat string_ranges(child)
140
130
  end
141
131
  if node.type == :DSTR && node.children.last.nil?
142
- # result.push Range.new(result.last.ending, result.last.ending)
143
132
  last = node.children[-2]
144
133
  unless last.nil?
145
134
  rng = Range.from_node(last)
@@ -8,17 +8,24 @@ module Solargraph
8
8
  include NodeMethods
9
9
 
10
10
  def process
11
- if other_class_eval?
12
- other_class = Solargraph::Pin::Namespace.new(
11
+ location = get_node_location(node)
12
+ parent = if other_class_eval?
13
+ Solargraph::Pin::Namespace.new(
14
+ location: location,
13
15
  type: :class,
14
16
  name: unpack_name(node.children[0].children[0])
15
17
  )
16
- make_block_in other_class.context
17
- process_children region.update(closure: other_class)
18
18
  else
19
- make_block_in nil
20
- process_children region.update(closure: pins.last)
19
+ region.closure
21
20
  end
21
+ pins.push Solargraph::Pin::Block.new(
22
+ location: location,
23
+ closure: parent,
24
+ receiver: node.children[0],
25
+ comments: comments_for(node),
26
+ scope: region.scope || region.closure.context.scope
27
+ )
28
+ process_children region.update(closure: pins.last)
22
29
  end
23
30
 
24
31
  private
@@ -28,17 +35,6 @@ module Solargraph
28
35
  node.children[0].children[1] == :class_eval &&
29
36
  [:COLON2, :CONST].include?(node.children[0].children[0].type)
30
37
  end
31
-
32
- def make_block_in context
33
- pins.push Solargraph::Pin::Block.new(
34
- location: get_node_location(node),
35
- context: context,
36
- closure: region.closure,
37
- receiver: node.children[0],
38
- comments: comments_for(node),
39
- scope: region.scope || region.closure.context.scope
40
- )
41
- end
42
38
  end
43
39
  end
44
40
  end
@@ -6,7 +6,6 @@ module Solargraph
6
6
  module NodeProcessors
7
7
  class DefNode < Parser::NodeProcessor::Base
8
8
  def process
9
- loc = get_node_location(node)
10
9
  methpin = Solargraph::Pin::Method.new(
11
10
  location: get_node_location(node),
12
11
  closure: region.closure,
@@ -11,8 +11,8 @@ module Solargraph
11
11
  closure: region.closure,
12
12
  comments: comments_for(node),
13
13
  name: node.children[0].children[0].to_s,
14
- # assignment: require_keyword?(node) ? nil : node.children[0].children[1],
15
- asgn_code: require_keyword?(node) ? nil: region.code_for(node.children[0].children[1]),
14
+ assignment: require_keyword?(node) ? nil : node.children[0].children[1],
15
+ asgn_code: require_keyword?(node) ? nil : region.code_for(node.children[0].children[1]),
16
16
  presence: region.closure.location.range,
17
17
  decl: require_keyword?(node) ? :kwarg : :kwoptarg
18
18
  )
@@ -45,6 +45,7 @@ module Solargraph
45
45
  register :IASGN, Rubyvm::NodeProcessors::IvasgnNode
46
46
  register :CVASGN, Rubyvm::NodeProcessors::CvasgnNode
47
47
  register :LASGN, Rubyvm::NodeProcessors::LvasgnNode
48
+ register :DASGN, Rubyvm::NodeProcessors::LvasgnNode
48
49
  register :DASGN_CURR, Rubyvm::NodeProcessors::LvasgnNode
49
50
  register :GASGN, Rubyvm::NodeProcessors::GvasgnNode
50
51
  register :CDECL, Rubyvm::NodeProcessors::CasgnNode
@@ -8,6 +8,7 @@ module Solargraph
8
8
  # @return [Parser::AST::Node]
9
9
  attr_reader :receiver
10
10
 
11
+ # @param args [Array<Parameter>]
11
12
  def initialize receiver: nil, args: [], context: nil, **splat
12
13
  super(**splat)
13
14
  @receiver = receiver
@@ -25,7 +26,7 @@ module Solargraph
25
26
  @binder || closure.binder
26
27
  end
27
28
 
28
- # @return [Array<String>]
29
+ # @return [Array<Parameter>]
29
30
  def parameters
30
31
  @parameters ||= []
31
32
  end
@@ -41,7 +41,7 @@ module Solargraph
41
41
  end
42
42
 
43
43
  def match_named_closure needle, haystack
44
- return true if needle == haystack
44
+ return true if needle == haystack || haystack.is_a?(Pin::Block)
45
45
  cursor = haystack
46
46
  until cursor.nil?
47
47
  return true if needle.path == cursor.path
@@ -9,8 +9,8 @@ module Solargraph
9
9
  # @return [::Symbol] :class or :module
10
10
  attr_reader :type
11
11
 
12
- # @param type [Symbol] :class or :module
13
- # @param visibility [Symbol] :public or :private
12
+ # @param type [::Symbol] :class or :module
13
+ # @param visibility [::Symbol] :public or :private
14
14
  # @param gates [Array<String>]
15
15
  def initialize type: :class, visibility: :public, gates: [''], **splat
16
16
  # super(location, namespace, name, comments)
@@ -3,8 +3,10 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Parameter < LocalVariable
6
+ # @return [Symbol]
6
7
  attr_reader :decl
7
8
 
9
+ # @return [String]
8
10
  attr_reader :asgn_code
9
11
 
10
12
  def initialize decl: :arg, asgn_code: nil, **splat
@@ -91,10 +93,6 @@ module Solargraph
91
93
  true
92
94
  end
93
95
 
94
- def probe api_map
95
- typify api_map
96
- end
97
-
98
96
  private
99
97
 
100
98
  # @return [YARD::Tags::Tag]
@@ -145,10 +143,7 @@ module Solargraph
145
143
  # meths.shift # Ignore the first one
146
144
  meths.each do |meth|
147
145
  found = nil
148
- params = meth.docstring.tags(:param)
149
- if params.empty?
150
- params = see_reference(docstring, api_map)
151
- end
146
+ params = meth.docstring.tags(:param) + see_reference(docstring, api_map)
152
147
  params.each do |p|
153
148
  next unless p.name == name
154
149
  found = p
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jaro_winkler'
4
+
5
+ module Solargraph
6
+ module Pin
7
+ class Search
8
+ class Result
9
+ # @return [Float]
10
+ attr_reader :match
11
+
12
+ # @return [Pin::Base]
13
+ attr_reader :pin
14
+
15
+ def initialize match, pin
16
+ @match = match
17
+ @pin = pin
18
+ end
19
+ end
20
+
21
+ # @param pins [Array<Pin::Base>]
22
+ # @param query [String]
23
+ def initialize pins, query
24
+ @pins = pins
25
+ @query = query
26
+ end
27
+
28
+ # @return [Array<Pin::Base>]
29
+ def results
30
+ @results ||= do_query
31
+ end
32
+
33
+ private
34
+
35
+ # @return [Array<Pin::Base>]
36
+ def do_query
37
+ return @pins if @query.nil? || @query.empty?
38
+ @pins.map do |pin|
39
+ match = [fuzzy_string_match(pin.path, @query), fuzzy_string_match(pin.name, @query)].max
40
+ Result.new(match, pin) if match > 0.7
41
+ end
42
+ .compact
43
+ .sort { |a, b| b.match <=> a.match }
44
+ .map(&:pin)
45
+ end
46
+
47
+ # @param str1 [String]
48
+ # @param str2 [String]
49
+ # @return [Float]
50
+ def fuzzy_string_match str1, str2
51
+ return (1.0 + (str2.length.to_f / str1.length.to_f)) if str1.downcase.include?(str2.downcase)
52
+ JaroWinkler.distance(str1, str2, ignore_case: true)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -30,6 +30,7 @@ module Solargraph
30
30
  autoload :DuckMethod, 'solargraph/pin/duck_method'
31
31
  autoload :Singleton, 'solargraph/pin/singleton'
32
32
  autoload :KeywordParam, 'solargraph/pin/keyword_param'
33
+ autoload :Search, 'solargraph/pin/search'
33
34
 
34
35
  ROOT_PIN = Pin::Namespace.new(type: :class, name: '', closure: nil)
35
36
  end
@@ -69,7 +69,7 @@ module Solargraph
69
69
  if node.is_a?(RubyVM::AbstractSyntaxTree::Node)
70
70
  Solargraph::Range.from_to(node.first_lineno - 1, node.first_column, node.last_lineno - 1, node.last_column)
71
71
  end
72
- elsif node.loc && node.loc.expression
72
+ elsif node&.loc && node.loc.expression
73
73
  from_expr(node.loc.expression)
74
74
  end
75
75
  end
@@ -360,7 +360,7 @@ module Solargraph
360
360
  skip = nil
361
361
  comments.lines.each { |l|
362
362
  # Trim the comment and minimum leading whitespace
363
- p = l.gsub(/^#+/, '')
363
+ p = l.force_encoding('UTF-8').encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
364
364
  if p.strip.empty?
365
365
  next unless started
366
366
  ctxt.concat p
@@ -12,7 +12,7 @@ module Solargraph
12
12
 
13
13
  private_class_method :new
14
14
 
15
- MACRO_REGEXP = /(@\!method|@\!attribute|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
15
+ MACRO_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
16
16
 
17
17
  # Generate the data.
18
18
  #
@@ -56,8 +56,10 @@ module Solargraph
56
56
  @pins ||= []
57
57
  end
58
58
 
59
+ # @param position [Solargraph::Position]
60
+ # @return [Solargraph::Pin::Closure]
59
61
  def closure_at(position)
60
- @pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
62
+ pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
61
63
  end
62
64
 
63
65
  def process_comment source_position, comment_position, comment
@@ -147,6 +149,27 @@ module Solargraph
147
149
  pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
148
150
  end
149
151
  end
152
+ when 'visibility'
153
+ begin
154
+ kind = directive.tag.text&.to_sym
155
+ return unless [:private, :protected, :public].include?(kind)
156
+
157
+ name = directive.tag.name
158
+ closure = closure_at(source_position) || @pins.first
159
+ if closure.location.range.start.line < comment_position.line
160
+ closure = closure_at(comment_position)
161
+ end
162
+ if closure.is_a?(Pin::Method) && no_empty_lines?(comment_position.line, source_position.line)
163
+ # @todo Smelly instance variable access
164
+ closure.instance_variable_set(:@visibility, kind)
165
+ else
166
+ matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == namespace && pin.context.scope == namespace.is_a?(Pin::Singleton) ? :class : :instance }
167
+ matches.each do |pin|
168
+ # @todo Smelly instance variable access
169
+ pin.instance_variable_set(:@visibility, kind)
170
+ end
171
+ end
172
+ end
150
173
  when 'parse'
151
174
  begin
152
175
  ns = closure_at(source_position)
@@ -176,6 +199,10 @@ module Solargraph
176
199
  end
177
200
  end
178
201
 
202
+ def no_empty_lines?(line1, line2)
203
+ @code.lines[line1..line2].none? { |line| line.strip.empty? }
204
+ end
205
+
179
206
  def remove_inline_comment_hashes comment
180
207
  ctxt = ''
181
208
  num = nil
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'jaro_winkler'
4
3
  require 'yard'
5
4
  require 'yard-solargraph'
6
5
  require 'set'
@@ -76,8 +75,7 @@ module Solargraph
76
75
  # @param query [String]
77
76
  # @return [Array<Pin::Base>]
78
77
  def query_symbols query
79
- return document_symbols if query && query.empty?
80
- document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
78
+ Pin::Search.new(document_symbols, query).results
81
79
  end
82
80
 
83
81
  # @param position [Position]
@@ -178,12 +176,5 @@ module Solargraph
178
176
  # Assuming the root pin is always valid
179
177
  found || pins.first
180
178
  end
181
-
182
- # @param str1 [String]
183
- # @param str2 [String]
184
- # @return [Boolean]
185
- def fuzzy_string_match str1, str2
186
- JaroWinkler.distance(str1, str2) > 0.6
187
- end
188
179
  end
189
180
  end
@@ -61,6 +61,19 @@ module Solargraph
61
61
  false
62
62
  end
63
63
 
64
+ # @param api_map [ApiMap]
65
+ # @param inferred [ComplexType]
66
+ # @param expected [ComplexType]
67
+ # @return [Boolean]
68
+ def all_types_match? api_map, inferred, expected
69
+ return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
70
+ inferred.each do |inf|
71
+ next if inf.duck_type?
72
+ return false unless expected.any? { |exp| exp == inf || either_way?(api_map, inf, exp) }
73
+ end
74
+ true
75
+ end
76
+
64
77
  # @param api_map [ApiMap]
65
78
  # @param expected [ComplexType]
66
79
  # @param inferred [ComplexType]
@@ -40,10 +40,12 @@ module Solargraph
40
40
  # @return [Array<Problem>]
41
41
  def problems
42
42
  @problems ||= begin
43
- method_tag_problems
44
- .concat variable_type_tag_problems
45
- .concat const_problems
46
- .concat call_problems
43
+ without_ignored(
44
+ method_tag_problems
45
+ .concat variable_type_tag_problems
46
+ .concat const_problems
47
+ .concat call_problems
48
+ )
47
49
  end
48
50
  end
49
51
 
@@ -84,12 +86,13 @@ module Solargraph
84
86
  # @param pin [Pin::Method]
85
87
  # @return [Array<Problem>]
86
88
  def method_return_type_problems_for pin
89
+ return [] if pin.is_a?(Pin::MethodAlias)
87
90
  result = []
88
91
  declared = pin.typify(api_map).self_to(pin.full_context.namespace)
89
92
  if declared.undefined?
90
93
  if pin.return_type.undefined? && rules.require_type_tags?
91
94
  result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}", pin: pin)
92
- elsif pin.return_type.defined?
95
+ elsif pin.return_type.defined? && !resolved_constant?(pin)
93
96
  result.push Problem.new(pin.location, "Unresolved return type #{pin.return_type} for #{pin.path}", pin: pin)
94
97
  elsif rules.must_tag_or_infer? && pin.probe(api_map).undefined?
95
98
  result.push Problem.new(pin.location, "Untyped method #{pin.path} could not be inferred")
@@ -102,7 +105,7 @@ module Solargraph
102
105
  result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
103
106
  end
104
107
  else
105
- unless (rules.rank > 1 ? types_match?(api_map, declared, inferred) : any_types_match?(api_map, declared, inferred))
108
+ unless (rules.rank > 1 ? all_types_match?(api_map, inferred, declared) : any_types_match?(api_map, declared, inferred))
106
109
  result.push Problem.new(pin.location, "Declared return type #{declared} does not match inferred type #{inferred} for #{pin.path}", pin: pin)
107
110
  end
108
111
  end
@@ -111,6 +114,20 @@ module Solargraph
111
114
  result
112
115
  end
113
116
 
117
+ # @todo This is not optimal. A better solution would probably be to mix
118
+ # namespace alias into types at the ApiMap level.
119
+ #
120
+ # @param pin [Pin::Base]
121
+ # @return [Boolean]
122
+ def resolved_constant? pin
123
+ api_map.get_constants('', pin.binder.tag)
124
+ .select { |p| p.name == pin.return_type.namespace }
125
+ .any? do |p|
126
+ inferred = p.infer(api_map)
127
+ ['Class', 'Module'].include?(inferred.name)
128
+ end
129
+ end
130
+
114
131
  def virtual_pin? pin
115
132
  pin.location && source_map.source.comment_at?(pin.location.range.ending)
116
133
  end
@@ -160,7 +177,7 @@ module Solargraph
160
177
  result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
161
178
  end
162
179
  else
163
- unless (rules.rank > 1 ? types_match?(api_map, declared, inferred) : any_types_match?(api_map, declared, inferred))
180
+ unless any_types_match?(api_map, declared, inferred)
164
181
  result.push Problem.new(pin.location, "Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
165
182
  end
166
183
  end
@@ -225,7 +242,7 @@ module Solargraph
225
242
  base = base.base
226
243
  end
227
244
  closest = found.typify(api_map) if found
228
- if !found || (closest.defined? && internal_or_core?(found))
245
+ if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
229
246
  unless ignored_pins.include?(found)
230
247
  result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
231
248
  @marked_ranges.push rng
@@ -402,6 +419,15 @@ module Solargraph
402
419
 
403
420
  # @param pin [Pin::Method]
404
421
  def arity_problems_for(pin, arguments, location)
422
+ ([pin] + pin.overloads).map do |p|
423
+ result = pin_arity_problems_for(p, arguments, location)
424
+ return [] if result.empty?
425
+ result
426
+ end.flatten.uniq(&:message)
427
+ end
428
+
429
+ # @param pin [Pin::Method]
430
+ def pin_arity_problems_for(pin, arguments, location)
405
431
  return [] unless pin.explicit?
406
432
  return [] if pin.parameters.empty? && arguments.empty?
407
433
  if pin.parameters.empty?
@@ -506,5 +532,12 @@ module Solargraph
506
532
  args.push Solargraph::Parser.chain_string('&') if with_block
507
533
  args
508
534
  end
535
+
536
+ def without_ignored problems
537
+ problems.reject do |problem|
538
+ node = source_map.source.node_at(problem.location.range.start.line, problem.location.range.start.column)
539
+ source_map.source.comments_for(node)&.include?('@sg-ignore')
540
+ end
541
+ end
509
542
  end
510
543
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.44.1'
4
+ VERSION = '0.47.2'
5
5
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'open3'
4
4
  require 'rubygems'
5
+ require 'json'
5
6
 
6
7
  module Solargraph
7
8
  # A workspace consists of the files in a project's directory and the
@@ -101,6 +101,7 @@ module Solargraph
101
101
  Override.method_return('File.dirname', 'String'),
102
102
  Override.method_return('File.extname', 'String'),
103
103
  Override.method_return('File.join', 'String'),
104
+ Override.method_return('File.open', 'File'),
104
105
 
105
106
  Override.from_comment('Float#+', %(
106
107
  @param y [Numeric]
@@ -110,14 +111,15 @@ module Solargraph
110
111
  Override.from_comment('Hash#[]', %(
111
112
  @return_value_parameter
112
113
  )),
113
-
114
114
  # @todo This override isn't robust enough. It needs to allow for
115
115
  # parameterized Hash types, e.g., [Hash{Symbol => String}].
116
116
  Override.from_comment('Hash#[]=', %(
117
117
  @param_tuple
118
118
  )),
119
-
120
119
  Override.method_return('Hash#merge', 'Hash'),
120
+ Override.from_comment('Hash#store', %{
121
+ @overload store(key, value)
122
+ }),
121
123
 
122
124
  Override.from_comment('Integer#+', %(
123
125
  @param y [Numeric]
@@ -181,6 +183,9 @@ module Solargraph
181
183
  )
182
184
 
183
185
  PINS = [
186
+ # HACK: Extending Hash is not accurate to the implementation, but
187
+ # accurate enough to the behavior
188
+ Pin::Reference::Extend.new(closure: Pin::Namespace.new(name: 'ENV'), name: 'Hash'),
184
189
  Pin::Reference::Superclass.new(closure: Pin::Namespace.new(name: 'File'), name: 'IO'),
185
190
  Pin::Reference::Superclass.new(closure: Pin::Namespace.new(name: 'Integer'), name: 'Numeric'),
186
191
  Pin::Reference::Superclass.new(closure: Pin::Namespace.new(name: 'Float'), name: 'Numeric')
@@ -107,6 +107,11 @@ module Solargraph
107
107
  @unresolved_requires ||= []
108
108
  end
109
109
 
110
+ # @return [Array<String>]
111
+ def missing_docs
112
+ @missing_docs ||= []
113
+ end
114
+
110
115
  # @param y [String]
111
116
  # @return [YARD::Registry]
112
117
  def load_yardoc y
@@ -196,10 +201,11 @@ module Solargraph
196
201
  required.merge @gemset.keys if required.include?('bundler/require')
197
202
  pins.replace core_pins
198
203
  unresolved_requires.clear
204
+ missing_docs.clear
199
205
  stdlib_pins.clear
200
206
  environ = Convention.for_global(self)
201
207
  done = []
202
- from_std = []
208
+ already_errored = []
203
209
  (required + environ.requires).each do |r|
204
210
  next if r.nil? || r.empty? || done.include?(r)
205
211
  done.push r
@@ -219,24 +225,18 @@ module Solargraph
219
225
  # YARD detects gems for certain libraries that do not have a yardoc
220
226
  # but exist in the stdlib. `fileutils` is an example. Treat those
221
227
  # cases as errors and check the stdlib yardoc.
222
- raise Gem::LoadError if yd.nil?
228
+ if yd.nil?
229
+ process_error(r, result, already_errored, nil)
230
+ next
231
+ end
223
232
  @gem_paths[spec.name] = spec.full_gem_path
224
233
  unless yardocs.include?(yd)
225
234
  yardocs.unshift yd
226
235
  result.concat process_yardoc yd, spec
227
236
  result.concat add_gem_dependencies(spec) if with_dependencies?
228
237
  end
229
- rescue Gem::LoadError, NoYardocError => e
230
- base = r.split('/').first
231
- next if from_std.include?(base)
232
- from_std.push base
233
- stdtmp = load_stdlib_pins(base)
234
- if stdtmp.empty?
235
- unresolved_requires.push r
236
- else
237
- stdlib_pins.concat stdtmp
238
- result.concat stdtmp
239
- end
238
+ rescue Gem::LoadError, NoYardocError
239
+ process_error(r, result, already_errored)
240
240
  end
241
241
  result.delete_if(&:nil?)
242
242
  unless result.empty?
@@ -253,6 +253,21 @@ module Solargraph
253
253
  pins.concat environ.pins
254
254
  end
255
255
 
256
+ def process_error(req, result, already_errored, yd = 1)
257
+ base = req.split('/').first
258
+ return if already_errored.include?(base)
259
+ already_errored.push base
260
+ stdtmp = load_stdlib_pins(base)
261
+ if yd.nil?
262
+ missing_docs.push req
263
+ elsif stdtmp.empty?
264
+ unresolved_requires.push req
265
+ else
266
+ stdlib_pins.concat stdtmp
267
+ result.concat stdtmp
268
+ end
269
+ end
270
+
256
271
  def process_gemsets
257
272
  return {} if directory.empty? || !File.file?(File.join(directory, 'Gemfile'))
258
273
  require_from_bundle(directory)
@@ -270,7 +285,7 @@ module Solargraph
270
285
  @gem_paths[depspec.name] = depspec.full_gem_path
271
286
  gy = yardoc_file_for_spec(depspec)
272
287
  if gy.nil?
273
- unresolved_requires.push dep.name
288
+ missing_docs.push dep.name
274
289
  else
275
290
  next if yardocs.include?(gy)
276
291
  yardocs.unshift gy
@@ -343,7 +358,9 @@ module Solargraph
343
358
  # @param path [String]
344
359
  # @return [Gem::Specification]
345
360
  def spec_for_require path
346
- spec = Gem::Specification.find_by_path(path) || Gem::Specification.find_by_name(path.split('/').first)
361
+ name = path.split('/').first
362
+ spec = Gem::Specification.find_by_name(name, @gemset[name])
363
+
347
364
  # Avoid loading the spec again if it's going to be skipped anyway
348
365
  return spec if @source_gems.include?(spec.name)
349
366
  # Avoid loading the spec again if it's already the correct version
data/lib/solargraph.rb CHANGED
@@ -59,8 +59,8 @@ module Solargraph
59
59
  #
60
60
  # @return [void]
61
61
  def self.with_clean_env &block
62
- meth = if Bundler.respond_to?(:with_unbundled_env)
63
- :with_unbundled_env
62
+ meth = if Bundler.respond_to?(:with_original_env)
63
+ :with_original_env
64
64
  else
65
65
  :with_clean_env
66
66
  end
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.44.1
4
+ version: 0.47.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-18 00:00:00.000000000 Z
11
+ date: 2022-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport
@@ -301,6 +301,7 @@ executables:
301
301
  extensions: []
302
302
  extra_rdoc_files: []
303
303
  files:
304
+ - ".github/workflows/rspec.yml"
304
305
  - ".gitignore"
305
306
  - ".rspec"
306
307
  - ".travis.yml"
@@ -491,6 +492,7 @@ files:
491
492
  - lib/solargraph/pin/reference/prepend.rb
492
493
  - lib/solargraph/pin/reference/require.rb
493
494
  - lib/solargraph/pin/reference/superclass.rb
495
+ - lib/solargraph/pin/search.rb
494
496
  - lib/solargraph/pin/singleton.rb
495
497
  - lib/solargraph/pin/symbol.rb
496
498
  - lib/solargraph/position.rb
@@ -572,7 +574,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
572
574
  - !ruby/object:Gem::Version
573
575
  version: '0'
574
576
  requirements: []
575
- rubygems_version: 3.1.6
577
+ rubygems_version: 3.3.7
576
578
  signing_key:
577
579
  specification_version: 4
578
580
  summary: A Ruby language server