solargraph 0.44.1 → 0.47.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +41 -0
- data/CHANGELOG.md +46 -0
- data/README.md +10 -2
- data/SPONSORS.md +3 -1
- data/lib/solargraph/api_map.rb +27 -22
- data/lib/solargraph/complex_type.rb +6 -2
- data/lib/solargraph/convention/rspec.rb +13 -4
- data/lib/solargraph/diagnostics/require_not_found.rb +16 -0
- data/lib/solargraph/diagnostics/rubocop.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/hover.rb +16 -4
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +1 -1
- data/lib/solargraph/language_server/uri_helpers.rb +1 -1
- data/lib/solargraph/parser/legacy/class_methods.rb +9 -8
- data/lib/solargraph/parser/legacy/node_processors/block_node.rb +13 -17
- data/lib/solargraph/parser/rubyvm/class_methods.rb +2 -13
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +13 -17
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -1
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +2 -2
- data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
- data/lib/solargraph/pin/block.rb +2 -1
- data/lib/solargraph/pin/local_variable.rb +1 -1
- data/lib/solargraph/pin/namespace.rb +2 -2
- data/lib/solargraph/pin/parameter.rb +3 -8
- data/lib/solargraph/pin/search.rb +56 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/range.rb +1 -1
- data/lib/solargraph/source.rb +1 -1
- data/lib/solargraph/source_map/mapper.rb +29 -2
- data/lib/solargraph/source_map.rb +1 -10
- data/lib/solargraph/type_checker/checks.rb +13 -0
- data/lib/solargraph/type_checker.rb +41 -8
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +1 -0
- data/lib/solargraph/yard_map/core_fills.rb +7 -2
- data/lib/solargraph/yard_map.rb +32 -15
- data/lib/solargraph.rb +2 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d35030ae56f6aaff108a24e4fb06713f911ba4366feb2223b24ad0ea4568522
|
4
|
+
data.tar.gz: a9eeaee16171bc762922ac55d10c61d53bcfe6ef1df0b20623c81e0978a80c7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
data/lib/solargraph/api_map.rb
CHANGED
@@ -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,
|
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
|
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
|
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
|
294
|
-
result =
|
295
|
-
|
296
|
-
type.
|
297
|
-
result.
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
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
|
-
|
387
|
-
|
388
|
-
|
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,
|
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
|
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]
|
@@ -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.
|
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
|
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
|
-
|
53
|
-
|
54
|
-
eoff =
|
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
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
12
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
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
|
data/lib/solargraph/pin/block.rb
CHANGED
@@ -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<
|
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
|
data/lib/solargraph/pin.rb
CHANGED
@@ -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
|
data/lib/solargraph/range.rb
CHANGED
@@ -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
|
72
|
+
elsif node&.loc && node.loc.expression
|
73
73
|
from_expr(node.loc.expression)
|
74
74
|
end
|
75
75
|
end
|
data/lib/solargraph/source.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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 ?
|
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
|
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
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/workspace.rb
CHANGED
@@ -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')
|
data/lib/solargraph/yard_map.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
230
|
-
|
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
|
-
|
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
|
-
|
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?(:
|
63
|
-
:
|
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.
|
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:
|
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.
|
577
|
+
rubygems_version: 3.3.7
|
576
578
|
signing_key:
|
577
579
|
specification_version: 4
|
578
580
|
summary: A Ruby language server
|