solargraph 0.43.3 → 0.44.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 +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/solargraph/complex_type.rb +4 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/language_server/host.rb +8 -4
- data/lib/solargraph/language_server/message/initialize.rb +7 -0
- data/lib/solargraph/language_server/message/initialized.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -0
- data/lib/solargraph/language_server/message/text_document.rb +18 -18
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +1 -0
- data/lib/solargraph/language_server/message.rb +2 -1
- data/lib/solargraph/library.rb +22 -20
- data/lib/solargraph/parser/legacy/class_methods.rb +9 -3
- data/lib/solargraph/parser/legacy/node_chainer.rb +17 -0
- data/lib/solargraph/parser/legacy/node_methods.rb +7 -0
- data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -2
- data/lib/solargraph/parser/rubyvm/class_methods.rb +7 -12
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +5 -0
- data/lib/solargraph/parser/rubyvm/node_methods.rb +23 -14
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -2
- data/lib/solargraph/pin/block.rb +19 -9
- data/lib/solargraph/pin/documenting.rb +1 -1
- data/lib/solargraph/pin/local_variable.rb +2 -14
- data/lib/solargraph/pin/namespace.rb +2 -2
- data/lib/solargraph/pin/parameter.rb +1 -4
- data/lib/solargraph/source/chain/link.rb +4 -0
- data/lib/solargraph/source/chain/q_call.rb +11 -0
- data/lib/solargraph/source/chain.rb +14 -1
- data/lib/solargraph/source.rb +1 -4
- data/lib/solargraph/source_map/clip.rb +5 -5
- data/lib/solargraph/source_map/mapper.rb +4 -4
- data/lib/solargraph/type_checker.rb +11 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +1 -1
- data/solargraph.gemspec +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8ff2cf72eecc4a36760b60491151cbedb17e11ac665ef20609e0291b2e4b64e
|
4
|
+
data.tar.gz: ea35a1bb406f5c185df0943b483676360b3c0e3df9f4fb476a246174dc37b542
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 152ad48cda1f002d12f4e27e11bbc090be72a113246521d1a03e4a82f0d920e885f39cf8eef46d12c588d66afe0b4835cb16b2192ceaa16f1ad6d8c9631a9677
|
7
|
+
data.tar.gz: ef1f6ecfa30e9eb58080cdf09c94e1611f35f8f2f64ecc8fcfb0e359aa4b95551cf5cfb7d1ec749e023bcd9045118bb33fc0bc1756c4449aa8959ce6aa73b6d8
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
## 0.44.3 - January 22, 2022
|
2
|
+
- TypeChecker validates aliased namespaces (#497)
|
3
|
+
- Always use reference YARD tags when resolving param types (#515) (#516)
|
4
|
+
- Skip method aliases in strict type checking
|
5
|
+
|
6
|
+
## 0.44.2 - November 23, 2021
|
7
|
+
- Scope local variables in class_eval blocks (#503)
|
8
|
+
- Fix invalid UTF-8 in node comments (#504)
|
9
|
+
|
10
|
+
## 0.44.1 - November 18, 2021
|
11
|
+
- Chain nil safety navigation operator (#420)
|
12
|
+
- Update closure and context for class_eval receiver (#487)
|
13
|
+
- SourceMap::Mapper handles invalid byte sequences (#474)
|
14
|
+
- Special handle var= references, which may use as var = (have space) (#498)
|
15
|
+
- Rebind define_method to self (#494)
|
16
|
+
|
17
|
+
## 0.44.0 - September 27, 2021
|
18
|
+
- Allow opening parenthesis, space, and comma when using Diff::LCS (#465)
|
19
|
+
- Support textDocument/documentHighlight
|
20
|
+
- Library#references_from performs shallow matches
|
21
|
+
|
1
22
|
## 0.43.3 - September 25, 2021
|
2
23
|
- Avoid Dir.chdir in Bundler processes (#481)
|
3
24
|
- Check stdlib for gems with empty yardocs
|
@@ -31,7 +31,7 @@ module Solargraph
|
|
31
31
|
# @param code [String]
|
32
32
|
# @return [Array(Array<String>, Array<String>)]
|
33
33
|
def generate_options filename, code
|
34
|
-
args = ['-f', 'j', filename]
|
34
|
+
args = ['-f', 'j', '--force-exclusion', filename]
|
35
35
|
base_options = RuboCop::Options.new
|
36
36
|
options, paths = base_options.parse(args)
|
37
37
|
options[:stdin] = code
|
@@ -18,7 +18,6 @@ module Solargraph
|
|
18
18
|
autoload :Dispatch, 'solargraph/language_server/host/dispatch'
|
19
19
|
autoload :MessageWorker, 'solargraph/language_server/host/message_worker'
|
20
20
|
|
21
|
-
|
22
21
|
include UriHelpers
|
23
22
|
include Logging
|
24
23
|
include Dispatch
|
@@ -543,10 +542,11 @@ module Solargraph
|
|
543
542
|
# @param line [Integer]
|
544
543
|
# @param column [Integer]
|
545
544
|
# @param strip [Boolean] Strip special characters from variable names
|
545
|
+
# @param only [Boolean] If true, search current file only
|
546
546
|
# @return [Array<Solargraph::Range>]
|
547
|
-
def references_from uri, line, column, strip: true
|
547
|
+
def references_from uri, line, column, strip: true, only: false
|
548
548
|
library = library_for(uri)
|
549
|
-
library.references_from(uri_to_file(uri), line, column, strip: strip)
|
549
|
+
library.references_from(uri_to_file(uri), line, column, strip: strip, only: only)
|
550
550
|
end
|
551
551
|
|
552
552
|
# @param query [String]
|
@@ -632,6 +632,7 @@ module Solargraph
|
|
632
632
|
'diagnostics' => false,
|
633
633
|
'formatting' => false,
|
634
634
|
'folding' => true,
|
635
|
+
'highlights' => true,
|
635
636
|
'logLevel' => 'warn'
|
636
637
|
}
|
637
638
|
end
|
@@ -716,7 +717,7 @@ module Solargraph
|
|
716
717
|
return change if diffs.length.zero? || diffs.length > 1 || diffs.first.length > 1
|
717
718
|
# @type [Diff::LCS::Change]
|
718
719
|
diff = diffs.first.first
|
719
|
-
return change unless diff.adding? && ['.', ':'].include?(diff.element)
|
720
|
+
return change unless diff.adding? && ['.', ':', '(', ',', ' '].include?(diff.element)
|
720
721
|
position = Solargraph::Position.from_offset(source.code, diff.position)
|
721
722
|
{
|
722
723
|
'range' => {
|
@@ -784,6 +785,9 @@ module Solargraph
|
|
784
785
|
},
|
785
786
|
'textDocument/codeAction' => {
|
786
787
|
codeActionProvider: true
|
788
|
+
},
|
789
|
+
'textDocument/documentHighlight' => {
|
790
|
+
documentHighlightProvider: true
|
787
791
|
}
|
788
792
|
}
|
789
793
|
end
|
@@ -36,6 +36,7 @@ module Solargraph
|
|
36
36
|
result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
|
37
37
|
result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
|
38
38
|
result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
|
39
|
+
result[:capabilities].merge! static_highlights unless dynamic_registration_for?('textDocument', 'documentHighlight')
|
39
40
|
# @todo Temporarily disabled
|
40
41
|
# result[:capabilities].merge! static_code_action unless dynamic_registration_for?('textDocument', 'codeAction')
|
41
42
|
set_result result
|
@@ -138,6 +139,12 @@ module Solargraph
|
|
138
139
|
}
|
139
140
|
end
|
140
141
|
|
142
|
+
def static_highlights
|
143
|
+
{
|
144
|
+
documentHighlightProvider: true
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
141
148
|
# @param section [String]
|
142
149
|
# @param capability [String]
|
143
150
|
# @return [Boolean]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph::LanguageServer::Message::TextDocument
|
4
|
+
class DocumentHighlight < Base
|
5
|
+
def process
|
6
|
+
locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'], strip: true, only: true)
|
7
|
+
result = locs.map do |loc|
|
8
|
+
{
|
9
|
+
range: loc.range.to_hash,
|
10
|
+
kind: 1
|
11
|
+
}
|
12
|
+
end
|
13
|
+
set_result result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -4,24 +4,24 @@ module Solargraph
|
|
4
4
|
module LanguageServer
|
5
5
|
module Message
|
6
6
|
module TextDocument
|
7
|
-
autoload :Base,
|
8
|
-
autoload :Completion,
|
9
|
-
autoload :DidOpen,
|
10
|
-
autoload :DidChange,
|
11
|
-
autoload :DidClose,
|
12
|
-
autoload :DidSave,
|
13
|
-
autoload :Hover,
|
14
|
-
autoload :SignatureHelp,
|
15
|
-
autoload :DiagnosticsQueue,
|
16
|
-
autoload :OnTypeFormatting,
|
17
|
-
autoload :Definition,
|
18
|
-
autoload :DocumentSymbol,
|
19
|
-
autoload :Formatting,
|
20
|
-
autoload :References,
|
21
|
-
autoload :Rename,
|
22
|
-
autoload :PrepareRename,
|
23
|
-
autoload :FoldingRange,
|
24
|
-
autoload :
|
7
|
+
autoload :Base, 'solargraph/language_server/message/text_document/base'
|
8
|
+
autoload :Completion, 'solargraph/language_server/message/text_document/completion'
|
9
|
+
autoload :DidOpen, 'solargraph/language_server/message/text_document/did_open'
|
10
|
+
autoload :DidChange, 'solargraph/language_server/message/text_document/did_change'
|
11
|
+
autoload :DidClose, 'solargraph/language_server/message/text_document/did_close'
|
12
|
+
autoload :DidSave, 'solargraph/language_server/message/text_document/did_save'
|
13
|
+
autoload :Hover, 'solargraph/language_server/message/text_document/hover'
|
14
|
+
autoload :SignatureHelp, 'solargraph/language_server/message/text_document/signature_help'
|
15
|
+
autoload :DiagnosticsQueue, 'solargraph/language_server/message/text_document/diagnostics_queue'
|
16
|
+
autoload :OnTypeFormatting, 'solargraph/language_server/message/text_document/on_type_formatting'
|
17
|
+
autoload :Definition, 'solargraph/language_server/message/text_document/definition'
|
18
|
+
autoload :DocumentSymbol, 'solargraph/language_server/message/text_document/document_symbol'
|
19
|
+
autoload :Formatting, 'solargraph/language_server/message/text_document/formatting'
|
20
|
+
autoload :References, 'solargraph/language_server/message/text_document/references'
|
21
|
+
autoload :Rename, 'solargraph/language_server/message/text_document/rename'
|
22
|
+
autoload :PrepareRename, 'solargraph/language_server/message/text_document/prepare_rename'
|
23
|
+
autoload :FoldingRange, 'solargraph/language_server/message/text_document/folding_range'
|
24
|
+
autoload :DocumentHighlight, 'solargraph/language_server/message/text_document/document_highlight'
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -22,6 +22,7 @@ module Solargraph::LanguageServer::Message::Workspace
|
|
22
22
|
(host.options['definitions'] ? y : n).push('textDocument/definition')
|
23
23
|
(host.options['references'] ? y : n).push('textDocument/references')
|
24
24
|
(host.options['folding'] ? y : n).push('textDocument/folding')
|
25
|
+
(host.options['highlights'] ? y : n).push('textDocument/documentHighlight')
|
25
26
|
host.register_capabilities y
|
26
27
|
host.unregister_capabilities n
|
27
28
|
end
|
@@ -73,7 +73,8 @@ module Solargraph
|
|
73
73
|
register 'textDocument/rename', TextDocument::Rename
|
74
74
|
register 'textDocument/prepareRename', TextDocument::PrepareRename
|
75
75
|
register 'textDocument/foldingRange', TextDocument::FoldingRange
|
76
|
-
register 'textDocument/codeAction', TextDocument::CodeAction
|
76
|
+
# register 'textDocument/codeAction', TextDocument::CodeAction
|
77
|
+
register 'textDocument/documentHighlight', TextDocument::DocumentHighlight
|
77
78
|
register 'workspace/didChangeWatchedFiles', Workspace::DidChangeWatchedFiles
|
78
79
|
register 'workspace/didChangeConfiguration', Workspace::DidChangeConfiguration
|
79
80
|
register 'workspace/didChangeWorkspaceFolders', Workspace::DidChangeWorkspaceFolders
|
data/lib/solargraph/library.rb
CHANGED
@@ -216,33 +216,35 @@ module Solargraph
|
|
216
216
|
# @param line [Integer]
|
217
217
|
# @param column [Integer]
|
218
218
|
# @param strip [Boolean] Strip special characters from variable names
|
219
|
+
# @param only [Boolean] Search for references in the current file only
|
219
220
|
# @return [Array<Solargraph::Range>]
|
220
221
|
# @todo Take a Location instead of filename/line/column
|
221
|
-
def references_from filename, line, column, strip: false
|
222
|
+
def references_from filename, line, column, strip: false, only: false
|
222
223
|
cursor = api_map.cursor_at(filename, Position.new(line, column))
|
223
224
|
clip = api_map.clip(cursor)
|
224
|
-
|
225
|
-
return []
|
225
|
+
pin = clip.define.first
|
226
|
+
return [] unless pin
|
226
227
|
result = []
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
228
|
+
files = if only
|
229
|
+
[api_map.source_map(filename)]
|
230
|
+
else
|
231
|
+
(workspace.sources + (@current ? [@current] : []))
|
232
|
+
end
|
233
|
+
files.uniq(&:filename).each do |source|
|
234
|
+
found = source.references(pin.name)
|
235
|
+
found.select! do |loc|
|
236
|
+
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
|
237
|
+
referenced && referenced.path == pin.path
|
238
|
+
end
|
239
|
+
# HACK: for language clients that exclude special characters from the start of variable names
|
240
|
+
if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
|
241
|
+
found.map! do |loc|
|
242
|
+
Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column))
|
241
243
|
end
|
242
|
-
result.concat(found.sort do |a, b|
|
243
|
-
a.range.start.line <=> b.range.start.line
|
244
|
-
end)
|
245
244
|
end
|
245
|
+
result.concat(found.sort do |a, b|
|
246
|
+
a.range.start.line <=> b.range.start.line
|
247
|
+
end)
|
246
248
|
end
|
247
249
|
result.uniq
|
248
250
|
end
|
@@ -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(
|
@@ -71,6 +71,23 @@ module Solargraph
|
|
71
71
|
else
|
72
72
|
raise "No idea what to do with #{n}"
|
73
73
|
end
|
74
|
+
elsif n.type == :csend
|
75
|
+
if n.children[0].is_a?(::Parser::AST::Node)
|
76
|
+
result.concat generate_links(n.children[0])
|
77
|
+
args = []
|
78
|
+
n.children[2..-1].each do |c|
|
79
|
+
args.push NodeChainer.chain(c)
|
80
|
+
end
|
81
|
+
result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
|
82
|
+
elsif n.children[0].nil?
|
83
|
+
args = []
|
84
|
+
n.children[2..-1].each do |c|
|
85
|
+
args.push NodeChainer.chain(c)
|
86
|
+
end
|
87
|
+
result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
|
88
|
+
else
|
89
|
+
raise "No idea what to do with #{n}"
|
90
|
+
end
|
74
91
|
elsif n.type == :self
|
75
92
|
result.push Chain::Head.new('self')
|
76
93
|
elsif n.type == :zsuper
|
@@ -178,6 +178,7 @@ module Solargraph
|
|
178
178
|
|
179
179
|
# @param cursor [Solargraph::Source::Cursor]
|
180
180
|
def find_recipient_node cursor
|
181
|
+
return repaired_find_recipient_node(cursor) if cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '('
|
181
182
|
source = cursor.source
|
182
183
|
position = cursor.position
|
183
184
|
offset = cursor.offset
|
@@ -210,6 +211,12 @@ module Solargraph
|
|
210
211
|
nil
|
211
212
|
end
|
212
213
|
|
214
|
+
def repaired_find_recipient_node cursor
|
215
|
+
cursor = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
|
216
|
+
node = cursor.source.tree_at(cursor.position.line, cursor.position.column).first
|
217
|
+
return node if node && node.type == :send
|
218
|
+
end
|
219
|
+
|
213
220
|
module DeepInference
|
214
221
|
class << self
|
215
222
|
CONDITIONAL = [:if, :unless]
|
@@ -5,16 +5,36 @@ module Solargraph
|
|
5
5
|
module Legacy
|
6
6
|
module NodeProcessors
|
7
7
|
class BlockNode < Parser::NodeProcessor::Base
|
8
|
+
include Legacy::NodeMethods
|
9
|
+
|
8
10
|
def process
|
11
|
+
location = get_node_location(node)
|
12
|
+
parent = if other_class_eval?
|
13
|
+
Solargraph::Pin::Namespace.new(
|
14
|
+
location: location,
|
15
|
+
type: :class,
|
16
|
+
name: unpack_name(node.children[0].children[0])
|
17
|
+
)
|
18
|
+
else
|
19
|
+
region.closure
|
20
|
+
end
|
9
21
|
pins.push Solargraph::Pin::Block.new(
|
10
|
-
location:
|
11
|
-
closure:
|
22
|
+
location: location,
|
23
|
+
closure: parent,
|
12
24
|
receiver: node.children[0],
|
13
25
|
comments: comments_for(node),
|
14
26
|
scope: region.scope || region.closure.context.scope
|
15
27
|
)
|
16
28
|
process_children region.update(closure: pins.last)
|
17
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def other_class_eval?
|
34
|
+
node.children[0].type == :send &&
|
35
|
+
node.children[0].children[1] == :class_eval &&
|
36
|
+
[:cbase, :const].include?(node.children[0].children[0]&.type)
|
37
|
+
end
|
18
38
|
end
|
19
39
|
end
|
20
40
|
end
|
@@ -29,22 +29,17 @@ 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
|
33
|
+
if name.end_with?("=")
|
34
|
+
reg = /#{Regexp.escape name[0..-2]}\s*=/
|
35
|
+
extract_offset = ->(code, offset) { reg.match(code, offset).offset(0) }
|
36
|
+
else
|
37
|
+
extract_offset = ->(code, offset) { [soff = code.index(name, offset), soff + name.length] }
|
38
|
+
end
|
43
39
|
inner_node_references(name, source.node).map do |n|
|
44
40
|
rng = Range.from_node(n)
|
45
41
|
offset = Position.to_offset(source.code, rng.start)
|
46
|
-
soff = source.code
|
47
|
-
eoff = soff + name.length
|
42
|
+
soff, eoff = extract_offset[source.code, offset]
|
48
43
|
Location.new(
|
49
44
|
source.filename,
|
50
45
|
Range.new(
|
@@ -60,6 +60,11 @@ module Solargraph
|
|
60
60
|
result.concat generate_links(c)
|
61
61
|
end
|
62
62
|
result.push Chain::Call.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
|
63
|
+
elsif n.type == :QCALL
|
64
|
+
n.children[0..-3].each do |c|
|
65
|
+
result.concat generate_links(c)
|
66
|
+
end
|
67
|
+
result.push Chain::QCall.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
|
63
68
|
elsif n.type == :ATTRASGN
|
64
69
|
result.concat generate_links(n.children[0])
|
65
70
|
result.push Chain::Call.new(n.children[1].to_s, node_to_argchains(n.children[2]), @in_block > 0 || block_passed?(n))
|
@@ -141,36 +141,45 @@ module Solargraph
|
|
141
141
|
class << self
|
142
142
|
protected
|
143
143
|
|
144
|
+
# @param cursor [Source::Cursor]
|
145
|
+
# @return [RubyVM::AbstractSyntaxTree::Node, nil]
|
144
146
|
def synchronized_find_recipient_node cursor
|
147
|
+
cursor = maybe_adjust_cursor(cursor)
|
145
148
|
source = cursor.source
|
146
149
|
position = cursor.position
|
147
150
|
offset = cursor.offset
|
148
151
|
tree = source.tree_at(position.line, position.column)
|
149
|
-
|
152
|
+
.select { |n| [:FCALL, :VCALL, :CALL].include?(n.type) }
|
153
|
+
unless source.repaired?
|
154
|
+
tree.shift while tree.first && !source.code_for(tree.first).strip.end_with?(')')
|
155
|
+
end
|
156
|
+
return tree.first if source.repaired? || source.code[0..offset-1] =~ /\(\s*$/
|
150
157
|
tree.each do |node|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
rng = Solargraph::Range.new(rng.start, position)
|
158
|
-
end
|
159
|
-
return node if rng.contain?(position)
|
160
|
-
elsif source.code[0..offset-1] =~ /\(\s*$/
|
161
|
-
break unless source.code_for(node).strip.end_with?(')')
|
162
|
-
return node
|
158
|
+
args = node.children.find { |c| Parser.is_ast_node?(c) && [:ARRAY, :ZARRAY, :LIST].include?(c.type) }
|
159
|
+
if args
|
160
|
+
match = source.code[0..offset-1].match(/,[^\)]*\z/)
|
161
|
+
rng = Solargraph::Range.from_node(args)
|
162
|
+
if match
|
163
|
+
rng = Solargraph::Range.new(rng.start, position)
|
163
164
|
end
|
165
|
+
return node if rng.contain?(position)
|
164
166
|
end
|
165
167
|
end
|
166
168
|
nil
|
167
169
|
end
|
168
170
|
|
171
|
+
# @param cursor [Source::Cursor]
|
172
|
+
# @return [Source::Cursor]
|
173
|
+
def maybe_adjust_cursor cursor
|
174
|
+
return cursor unless (cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '(') || [',', ' '].include?(cursor.source.code[cursor.offset - 1])
|
175
|
+
cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
|
176
|
+
end
|
177
|
+
|
169
178
|
def unsynchronized_find_recipient_node cursor
|
170
179
|
source = cursor.source
|
171
180
|
position = cursor.position
|
172
181
|
offset = cursor.offset
|
173
|
-
if source.code[0..offset-1] =~ /\([A-Zaz0-9_\s]*\z$/
|
182
|
+
if source.code[0..offset-1] =~ /\([A-Zaz0-9_\s]*\z$/
|
174
183
|
tree = source.tree_at(position.line, position.column - 1)
|
175
184
|
if tree.first && [:FCALL, :VCALL, :CALL].include?(tree.first.type)
|
176
185
|
return tree.first
|
@@ -5,16 +5,36 @@ module Solargraph
|
|
5
5
|
module Rubyvm
|
6
6
|
module NodeProcessors
|
7
7
|
class BlockNode < Parser::NodeProcessor::Base
|
8
|
+
include NodeMethods
|
9
|
+
|
8
10
|
def process
|
11
|
+
location = get_node_location(node)
|
12
|
+
parent = if other_class_eval?
|
13
|
+
Solargraph::Pin::Namespace.new(
|
14
|
+
location: location,
|
15
|
+
type: :class,
|
16
|
+
name: unpack_name(node.children[0].children[0])
|
17
|
+
)
|
18
|
+
else
|
19
|
+
region.closure
|
20
|
+
end
|
9
21
|
pins.push Solargraph::Pin::Block.new(
|
10
|
-
location:
|
11
|
-
closure:
|
22
|
+
location: location,
|
23
|
+
closure: parent,
|
12
24
|
receiver: node.children[0],
|
13
25
|
comments: comments_for(node),
|
14
26
|
scope: region.scope || region.closure.context.scope
|
15
27
|
)
|
16
28
|
process_children region.update(closure: pins.last)
|
17
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def other_class_eval?
|
34
|
+
node.children[0].type == :CALL &&
|
35
|
+
node.children[0].children[1] == :class_eval &&
|
36
|
+
[:COLON2, :CONST].include?(node.children[0].children[0].type)
|
37
|
+
end
|
18
38
|
end
|
19
39
|
end
|
20
40
|
end
|
data/lib/solargraph/pin/block.rb
CHANGED
@@ -8,9 +8,10 @@ module Solargraph
|
|
8
8
|
# @return [Parser::AST::Node]
|
9
9
|
attr_reader :receiver
|
10
10
|
|
11
|
-
def initialize receiver: nil, args: [], **splat
|
11
|
+
def initialize receiver: nil, args: [], context: nil, **splat
|
12
12
|
super(**splat)
|
13
13
|
@receiver = receiver
|
14
|
+
@context = context
|
14
15
|
@parameters = args
|
15
16
|
end
|
16
17
|
|
@@ -44,15 +45,24 @@ module Solargraph
|
|
44
45
|
return nil unless api_map.rebindable_method_names.include?(word)
|
45
46
|
chain = Parser.chain(receiver, location.filename)
|
46
47
|
locals = api_map.source_map(location.filename).locals_at(location)
|
47
|
-
|
48
|
+
links_last_word = chain.links.last.word
|
49
|
+
if %w[instance_eval instance_exec class_eval class_exec module_eval module_exec].include?(links_last_word)
|
48
50
|
return chain.base.infer(api_map, self, locals)
|
49
|
-
|
50
|
-
|
51
|
-
if
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
end
|
52
|
+
if 'define_method' == links_last_word and chain.define(api_map, self, locals).first&.path == 'Module#define_method' # change class type to instance type
|
53
|
+
if chain.links.size > 1 # Class.define_method
|
54
|
+
ty = chain.base.infer(api_map, self, locals)
|
55
|
+
return Solargraph::ComplexType.parse(ty.namespace)
|
56
|
+
else # define_method without self
|
57
|
+
return Solargraph::ComplexType.parse(closure.binder.namespace)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# other case without early return, read block yieldself tags
|
61
|
+
receiver_pin = chain.define(api_map, self, locals).first
|
62
|
+
if receiver_pin && receiver_pin.docstring
|
63
|
+
ys = receiver_pin.docstring.tag(:yieldself)
|
64
|
+
if ys && ys.types && !ys.types.empty?
|
65
|
+
return ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
|
56
66
|
end
|
57
67
|
end
|
58
68
|
nil
|
@@ -18,19 +18,7 @@ module Solargraph
|
|
18
18
|
true
|
19
19
|
end
|
20
20
|
|
21
|
-
# @param
|
22
|
-
# @param position [Position, Array(Integer, Integer)] The caller's position
|
23
|
-
# @return [Boolean]
|
24
|
-
def visible_from?(other, position)
|
25
|
-
position = Position.normalize(position)
|
26
|
-
other.filename == filename &&
|
27
|
-
match_tags(other.full_context.tag, full_context.tag) &&
|
28
|
-
(other == closure ||
|
29
|
-
(closure.location.range.contain?(other.location.range.start) && closure.location.range.contain?(other.location.range.ending))
|
30
|
-
) &&
|
31
|
-
presence.contain?(position)
|
32
|
-
end
|
33
|
-
|
21
|
+
# @param other_closure [Pin::Closure]
|
34
22
|
# @param other_loc [Location]
|
35
23
|
def visible_at?(other_closure, other_loc)
|
36
24
|
return true if location.filename == other_loc.filename &&
|
@@ -53,7 +41,7 @@ module Solargraph
|
|
53
41
|
end
|
54
42
|
|
55
43
|
def match_named_closure needle, haystack
|
56
|
-
return true if needle == haystack
|
44
|
+
return true if needle == haystack || haystack.is_a?(Pin::Block)
|
57
45
|
cursor = haystack
|
58
46
|
until cursor.nil?
|
59
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)
|
@@ -145,10 +145,7 @@ module Solargraph
|
|
145
145
|
# meths.shift # Ignore the first one
|
146
146
|
meths.each do |meth|
|
147
147
|
found = nil
|
148
|
-
params = meth.docstring.tags(:param)
|
149
|
-
if params.empty?
|
150
|
-
params = see_reference(docstring, api_map)
|
151
|
-
end
|
148
|
+
params = meth.docstring.tags(:param) + see_reference(docstring, api_map)
|
152
149
|
params.each do |p|
|
153
150
|
next unless p.name == name
|
154
151
|
found = p
|
@@ -11,6 +11,7 @@ module Solargraph
|
|
11
11
|
class Chain
|
12
12
|
autoload :Link, 'solargraph/source/chain/link'
|
13
13
|
autoload :Call, 'solargraph/source/chain/call'
|
14
|
+
autoload :QCall, 'solargraph/source/chain/q_call'
|
14
15
|
autoload :Variable, 'solargraph/source/chain/variable'
|
15
16
|
autoload :ClassVariable, 'solargraph/source/chain/class_variable'
|
16
17
|
autoload :Constant, 'solargraph/source/chain/constant'
|
@@ -76,7 +77,8 @@ module Solargraph
|
|
76
77
|
# @return [ComplexType]
|
77
78
|
def infer api_map, name_pin, locals
|
78
79
|
pins = define(api_map, name_pin, locals)
|
79
|
-
infer_first_defined(pins, links.last.last_context, api_map)
|
80
|
+
type = infer_first_defined(pins, links.last.last_context, api_map)
|
81
|
+
maybe_nil(type)
|
80
82
|
end
|
81
83
|
|
82
84
|
# @return [Boolean]
|
@@ -101,6 +103,10 @@ module Solargraph
|
|
101
103
|
@splat
|
102
104
|
end
|
103
105
|
|
106
|
+
def nullable?
|
107
|
+
links.any?(&:nullable?)
|
108
|
+
end
|
109
|
+
|
104
110
|
private
|
105
111
|
|
106
112
|
# @param pins [Array<Pin::Base>]
|
@@ -146,6 +152,13 @@ module Solargraph
|
|
146
152
|
return type if context.nil? || context.return_type.undefined?
|
147
153
|
type.self_to(context.return_type.namespace)
|
148
154
|
end
|
155
|
+
|
156
|
+
# @param type [ComplexType]
|
157
|
+
def maybe_nil type
|
158
|
+
return type if type.undefined? || type.void? || type.nullable?
|
159
|
+
return type unless nullable?
|
160
|
+
ComplexType.try_parse("#{type}, nil")
|
161
|
+
end
|
149
162
|
end
|
150
163
|
end
|
151
164
|
end
|
data/lib/solargraph/source.rb
CHANGED
@@ -42,7 +42,6 @@ module Solargraph
|
|
42
42
|
@version = version
|
43
43
|
@domains = []
|
44
44
|
begin
|
45
|
-
# @node, @comments = Source.parse_with_comments(@code, filename)
|
46
45
|
@node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
|
47
46
|
@parsed = true
|
48
47
|
rescue Parser::SyntaxError, EncodingError => e
|
@@ -336,7 +335,6 @@ module Solargraph
|
|
336
335
|
# @param parent [Symbol]
|
337
336
|
# @return [void]
|
338
337
|
def inner_folding_ranges top, result = [], parent = nil
|
339
|
-
# return unless top.is_a?(::Parser::AST::Node)
|
340
338
|
return unless Parser.is_ast_node?(top)
|
341
339
|
if FOLDING_NODE_TYPES.include?(top.type)
|
342
340
|
# @todo Smelly exception for hash's first-level array in RubyVM
|
@@ -362,7 +360,7 @@ module Solargraph
|
|
362
360
|
skip = nil
|
363
361
|
comments.lines.each { |l|
|
364
362
|
# Trim the comment and minimum leading whitespace
|
365
|
-
p = l.gsub(/^#+/, '')
|
363
|
+
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
|
366
364
|
if p.strip.empty?
|
367
365
|
next unless started
|
368
366
|
ctxt.concat p
|
@@ -433,7 +431,6 @@ module Solargraph
|
|
433
431
|
# @return [void]
|
434
432
|
def inner_tree_at node, position, stack
|
435
433
|
return if node.nil?
|
436
|
-
# here = Range.from_to(node.loc.expression.line, node.loc.expression.column, node.loc.expression.last_line, node.loc.expression.last_column)
|
437
434
|
here = Range.from_node(node)
|
438
435
|
if here.contain?(position) || colonized(here, position, node)
|
439
436
|
stack.unshift node
|
@@ -53,11 +53,7 @@ module Solargraph
|
|
53
53
|
#
|
54
54
|
# @return [Array<Solargraph::Pin::Base>]
|
55
55
|
def locals
|
56
|
-
|
57
|
-
adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
|
58
|
-
@locals ||= source_map.locals.select { |pin|
|
59
|
-
pin.visible_from?(block, adj_pos)
|
60
|
-
}.reverse
|
56
|
+
@locals ||= source_map.locals_at(location)
|
61
57
|
end
|
62
58
|
|
63
59
|
def gates
|
@@ -92,6 +88,10 @@ module Solargraph
|
|
92
88
|
@source_map ||= api_map.source_map(cursor.filename)
|
93
89
|
end
|
94
90
|
|
91
|
+
def location
|
92
|
+
Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
|
93
|
+
end
|
94
|
+
|
95
95
|
# @return [Solargraph::Pin::Base]
|
96
96
|
def block
|
97
97
|
@block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
|
@@ -61,7 +61,7 @@ module Solargraph
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def process_comment source_position, comment_position, comment
|
64
|
-
return unless comment =~ MACRO_REGEXP
|
64
|
+
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
|
65
65
|
cmnt = remove_inline_comment_hashes(comment)
|
66
66
|
parse = Solargraph::Source.parse_docstring(cmnt)
|
67
67
|
last_line = 0
|
@@ -169,7 +169,7 @@ module Solargraph
|
|
169
169
|
# @todo Handle parser errors in !parse directives
|
170
170
|
end
|
171
171
|
when 'domain'
|
172
|
-
namespace = closure_at(source_position)
|
172
|
+
namespace = closure_at(source_position) || Pin::ROOT_PIN
|
173
173
|
namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
|
174
174
|
when 'override'
|
175
175
|
pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
|
@@ -182,7 +182,7 @@ module Solargraph
|
|
182
182
|
started = false
|
183
183
|
comment.lines.each { |l|
|
184
184
|
# Trim the comment and minimum leading whitespace
|
185
|
-
p = l.gsub(/^#/, '')
|
185
|
+
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#/, '')
|
186
186
|
if num.nil? && !p.strip.empty?
|
187
187
|
num = p.index(/[^ ]/)
|
188
188
|
started = true
|
@@ -197,7 +197,7 @@ module Solargraph
|
|
197
197
|
|
198
198
|
# @return [void]
|
199
199
|
def process_comment_directives
|
200
|
-
return unless @code =~ MACRO_REGEXP
|
200
|
+
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
|
201
201
|
code_lines = @code.lines
|
202
202
|
@source.associated_comments.each do |line, comments|
|
203
203
|
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|
@@ -84,12 +84,13 @@ module Solargraph
|
|
84
84
|
# @param pin [Pin::Method]
|
85
85
|
# @return [Array<Problem>]
|
86
86
|
def method_return_type_problems_for pin
|
87
|
+
return [] if pin.is_a?(Pin::MethodAlias)
|
87
88
|
result = []
|
88
89
|
declared = pin.typify(api_map).self_to(pin.full_context.namespace)
|
89
90
|
if declared.undefined?
|
90
91
|
if pin.return_type.undefined? && rules.require_type_tags?
|
91
92
|
result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}", pin: pin)
|
92
|
-
elsif pin.return_type.defined?
|
93
|
+
elsif pin.return_type.defined? && !resolved_constant?(pin)
|
93
94
|
result.push Problem.new(pin.location, "Unresolved return type #{pin.return_type} for #{pin.path}", pin: pin)
|
94
95
|
elsif rules.must_tag_or_infer? && pin.probe(api_map).undefined?
|
95
96
|
result.push Problem.new(pin.location, "Untyped method #{pin.path} could not be inferred")
|
@@ -111,6 +112,15 @@ module Solargraph
|
|
111
112
|
result
|
112
113
|
end
|
113
114
|
|
115
|
+
# @todo This is not optimal. A better solution would probably be to mix
|
116
|
+
# namespace alias into types at the ApiMap level.
|
117
|
+
#
|
118
|
+
# @param pin [Pin::Base]
|
119
|
+
# @return [Boolean]
|
120
|
+
def resolved_constant? pin
|
121
|
+
api_map.get_constants('', pin.binder.tag).any? { |pin| pin.name == pin.return_type.namespace && ['Class', 'Module'].include?(pin.return_type.name) }
|
122
|
+
end
|
123
|
+
|
114
124
|
def virtual_pin? pin
|
115
125
|
pin.location && source_map.source.comment_at?(pin.location.range.ending)
|
116
126
|
end
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -88,7 +88,7 @@ module Solargraph
|
|
88
88
|
@rebindable_method_names ||= pins_by_class(Pin::Method)
|
89
89
|
.select { |pin| pin.comments && pin.comments.include?('@yieldself') }
|
90
90
|
.map(&:name)
|
91
|
-
.concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec'])
|
91
|
+
.concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'])
|
92
92
|
.to_set
|
93
93
|
end
|
94
94
|
|
data/solargraph.gemspec
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.add_runtime_dependency 'tilt', '~> 2.0'
|
35
35
|
s.add_runtime_dependency 'yard', '~> 0.9', '>= 0.9.24'
|
36
36
|
|
37
|
-
s.add_development_dependency 'pry'
|
37
|
+
s.add_development_dependency 'pry'
|
38
38
|
s.add_development_dependency 'public_suffix', '~> 3.1'
|
39
39
|
s.add_development_dependency 'rspec', '~> 3.5', '>= 3.5.0'
|
40
40
|
s.add_development_dependency 'simplecov', '~> 0.14'
|
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.44.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:
|
11
|
+
date: 2022-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -222,16 +222,16 @@ dependencies:
|
|
222
222
|
name: pry
|
223
223
|
requirement: !ruby/object:Gem::Requirement
|
224
224
|
requirements:
|
225
|
-
- - "
|
225
|
+
- - ">="
|
226
226
|
- !ruby/object:Gem::Version
|
227
|
-
version: 0
|
227
|
+
version: '0'
|
228
228
|
type: :development
|
229
229
|
prerelease: false
|
230
230
|
version_requirements: !ruby/object:Gem::Requirement
|
231
231
|
requirements:
|
232
|
-
- - "
|
232
|
+
- - ">="
|
233
233
|
- !ruby/object:Gem::Version
|
234
|
-
version: 0
|
234
|
+
version: '0'
|
235
235
|
- !ruby/object:Gem::Dependency
|
236
236
|
name: public_suffix
|
237
237
|
requirement: !ruby/object:Gem::Requirement
|
@@ -381,6 +381,7 @@ files:
|
|
381
381
|
- lib/solargraph/language_server/message/text_document/did_close.rb
|
382
382
|
- lib/solargraph/language_server/message/text_document/did_open.rb
|
383
383
|
- lib/solargraph/language_server/message/text_document/did_save.rb
|
384
|
+
- lib/solargraph/language_server/message/text_document/document_highlight.rb
|
384
385
|
- lib/solargraph/language_server/message/text_document/document_symbol.rb
|
385
386
|
- lib/solargraph/language_server/message/text_document/folding_range.rb
|
386
387
|
- lib/solargraph/language_server/message/text_document/formatting.rb
|
@@ -509,6 +510,7 @@ files:
|
|
509
510
|
- lib/solargraph/source/chain/link.rb
|
510
511
|
- lib/solargraph/source/chain/literal.rb
|
511
512
|
- lib/solargraph/source/chain/or.rb
|
513
|
+
- lib/solargraph/source/chain/q_call.rb
|
512
514
|
- lib/solargraph/source/chain/variable.rb
|
513
515
|
- lib/solargraph/source/chain/z_super.rb
|
514
516
|
- lib/solargraph/source/change.rb
|