solargraph 0.60.4 → 0.62.0
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/.github/workflows/linting.yml +24 -2
- data/.github/workflows/plugins.yml +19 -1
- data/.github/workflows/rspec.yml +17 -2
- data/.github/workflows/typecheck.yml +6 -0
- data/CHANGELOG.md +54 -0
- data/Gemfile +0 -3
- data/lib/solargraph/api_map/index.rb +28 -4
- data/lib/solargraph/api_map/store.rb +19 -0
- data/lib/solargraph/api_map.rb +91 -80
- data/lib/solargraph/cache_dir.rb +58 -0
- data/lib/solargraph/collection/base.rb +50 -0
- data/lib/solargraph/collection/core.rb +17 -0
- data/lib/solargraph/collection/gem.rb +59 -0
- data/lib/solargraph/collection/stdlib.rb +25 -0
- data/lib/solargraph/collection.rb +30 -0
- data/lib/solargraph/complex_type/unique_type.rb +13 -0
- data/lib/solargraph/complex_type.rb +23 -3
- data/lib/solargraph/convention.rb +5 -7
- data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
- data/lib/solargraph/diagnostics/type_check.rb +0 -1
- data/lib/solargraph/external.rb +187 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +4 -2
- data/lib/solargraph/language_server/host.rb +10 -2
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +10 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +5 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
- data/lib/solargraph/library.rb +26 -53
- data/lib/solargraph/metagem.rb +80 -0
- data/lib/solargraph/parser/node_processor/base.rb +6 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
- data/lib/solargraph/parser/parser_gem/node_methods.rb +29 -6
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition/class_assignment_node.rb +98 -0
- data/lib/solargraph/parser/parser_gem/node_processors/class_definition.rb +54 -0
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_assignment_node.rb +65 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_definition_node.rb +97 -0
- data/lib/solargraph/parser/parser_gem/node_processors/data_definition.rb +110 -0
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +185 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node.rb +66 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node.rb +108 -0
- data/lib/solargraph/parser/parser_gem/node_processors/struct_definition.rb +170 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +33 -29
- data/lib/solargraph/pin/base.rb +25 -1
- data/lib/solargraph/pin/base_variable.rb +31 -1
- data/lib/solargraph/pin/callable.rb +11 -2
- data/lib/solargraph/pin/closure.rb +17 -0
- data/lib/solargraph/pin/delegated_method.rb +5 -0
- data/lib/solargraph/pin/duck_method.rb +36 -16
- data/lib/solargraph/pin/factory_parameter.rb +84 -0
- data/lib/solargraph/pin/instance_variable.rb +45 -0
- data/lib/solargraph/pin/method.rb +10 -0
- data/lib/solargraph/pin/method_alias.rb +4 -0
- data/lib/solargraph/pin/parameter.rb +1 -1
- data/lib/solargraph/pin/reference/included_mixin.rb +22 -0
- data/lib/solargraph/pin/reference.rb +1 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/plugin/active_support.rb +100 -0
- data/lib/solargraph/plugin/addon.rb +16 -0
- data/lib/solargraph/plugin/base.rb +25 -0
- data/lib/solargraph/plugin/panel.rb +37 -0
- data/lib/solargraph/plugin.rb +26 -0
- data/lib/solargraph/rbs_collection.rb +119 -0
- data/lib/solargraph/rbs_map/base.rb +31 -0
- data/lib/solargraph/rbs_map/conversions.rb +109 -48
- data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
- data/lib/solargraph/rbs_map/core_fills.rb +1 -1
- data/lib/solargraph/rbs_map/gem.rb +16 -0
- data/lib/solargraph/rbs_map/helpers.rb +61 -0
- data/lib/solargraph/rbs_map/path.rb +19 -0
- data/lib/solargraph/rbs_map/stdlib.rb +24 -0
- data/lib/solargraph/rbs_map.rb +7 -198
- data/lib/solargraph/rbs_translator.rb +105 -70
- data/lib/solargraph/repo.rb +177 -0
- data/lib/solargraph/shell.rb +49 -99
- data/lib/solargraph/source/chain/call.rb +58 -14
- data/lib/solargraph/source/chain/literal.rb +17 -17
- data/lib/solargraph/source/chain/parameter.rb +79 -0
- data/lib/solargraph/source/chain.rb +8 -0
- data/lib/solargraph/source/node_map.rb +27 -0
- data/lib/solargraph/source/source_chainer.rb +40 -44
- data/lib/solargraph/source.rb +17 -0
- data/lib/solargraph/source_map/call.rb +18 -0
- data/lib/solargraph/source_map/clip.rb +5 -3
- data/lib/solargraph/source_map/mapper.rb +6 -2
- data/lib/solargraph/source_map.rb +28 -9
- data/lib/solargraph/type_checker/rules.rb +3 -2
- data/lib/solargraph/type_checker.rb +4 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +0 -1
- data/lib/solargraph/yard_map/cache.rb +1 -1
- data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives.rb +5 -2
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/macro.rb +85 -6
- data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
- data/lib/solargraph/yard_map/mapper.rb +2 -2
- data/lib/solargraph/yard_map.rb +1 -1
- data/lib/solargraph/yardoc.rb +43 -60
- data/lib/solargraph.rb +8 -3
- data/rbs/fills/boolean/0/boolean.rbs +12 -0
- data/solargraph.gemspec +2 -2
- metadata +41 -18
- data/lib/solargraph/convention/active_support_concern.rb +0 -111
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +0 -61
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +0 -93
- data/lib/solargraph/convention/data_definition.rb +0 -108
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +0 -62
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +0 -103
- data/lib/solargraph/convention/struct_definition.rb +0 -168
- data/lib/solargraph/doc_map.rb +0 -439
- data/lib/solargraph/gem_pins.rb +0 -87
- data/lib/solargraph/pin_cache.rb +0 -248
- data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
- data/lib/solargraph/workspace/gemspecs.rb +0 -373
|
@@ -12,7 +12,7 @@ module Solargraph
|
|
|
12
12
|
|
|
13
13
|
private_class_method :new
|
|
14
14
|
|
|
15
|
-
DIRECTIVE_REGEXP = /(@!method|@!attribute|@!visibility|@!domain|@!macro|@!parse|@!override)/
|
|
15
|
+
DIRECTIVE_REGEXP = /(@!method|@method|@!attribute|@!visibility|@!scope|@!domain|@!macro|@!parse|@!override)/
|
|
16
16
|
|
|
17
17
|
# Generate the data.
|
|
18
18
|
#
|
|
@@ -104,9 +104,13 @@ module Solargraph
|
|
|
104
104
|
directive_processor = YardMap::Directives.for(directive)
|
|
105
105
|
return unless directive_processor
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
new_pins = directive_processor.process_directive(
|
|
108
108
|
@source, @pins, source_position, comment_position, directive
|
|
109
109
|
)
|
|
110
|
+
# A @!scope directive in the indented text of another directive applies
|
|
111
|
+
# only to the object that directive defines.
|
|
112
|
+
YardMap::Directives::ScopeDirective.apply_nested directive, new_pins
|
|
113
|
+
@pins += new_pins
|
|
110
114
|
end
|
|
111
115
|
|
|
112
116
|
# @param comment [String]
|
|
@@ -12,6 +12,7 @@ module Solargraph
|
|
|
12
12
|
autoload :Clip, 'solargraph/source_map/clip'
|
|
13
13
|
autoload :Completion, 'solargraph/source_map/completion'
|
|
14
14
|
autoload :Data, 'solargraph/source_map/data'
|
|
15
|
+
autoload :Call, 'solargraph/source_map/call'
|
|
15
16
|
|
|
16
17
|
# @return [Source]
|
|
17
18
|
attr_reader :source
|
|
@@ -82,6 +83,16 @@ module Solargraph
|
|
|
82
83
|
pins_by_class(Pin::Reference::Require)
|
|
83
84
|
end
|
|
84
85
|
|
|
86
|
+
def calls *method_names
|
|
87
|
+
symbolized = method_names.map(&:to_sym)
|
|
88
|
+
node_map.find_by_type(:send).select { |node| node.children[0].nil? && symbolized.include?(node.children[1].to_sym) }
|
|
89
|
+
.map { |node| Call.new(self, Parser.chain(node), locate_namespace_pin(node.loc.line, node.loc.column)) }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def node_map
|
|
93
|
+
@node_map ||= Source::NodeMap.new(source.node)
|
|
94
|
+
end
|
|
95
|
+
|
|
85
96
|
# @return [Environ]
|
|
86
97
|
def conventions_environ
|
|
87
98
|
@conventions_environ ||= Environ.new
|
|
@@ -128,6 +139,10 @@ module Solargraph
|
|
|
128
139
|
_locate_pin line, character, Pin::Namespace, Pin::Method
|
|
129
140
|
end
|
|
130
141
|
|
|
142
|
+
def locate_namespace_pin line, character
|
|
143
|
+
_locate_pin line, character, Pin::Namespace, Pin::Singleton
|
|
144
|
+
end
|
|
145
|
+
|
|
131
146
|
# @param line [Integer]
|
|
132
147
|
# @param character [Integer]
|
|
133
148
|
# @return [Pin::Closure]
|
|
@@ -190,12 +205,14 @@ module Solargraph
|
|
|
190
205
|
end
|
|
191
206
|
end
|
|
192
207
|
|
|
193
|
-
private
|
|
194
|
-
|
|
195
208
|
# @return [Array<Pin::Base>]
|
|
196
|
-
|
|
209
|
+
def convention_pins
|
|
210
|
+
@convention_pins || []
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
private
|
|
197
214
|
|
|
198
|
-
# @return [Hash{Class
|
|
215
|
+
# @return [Hash{Class, Pin::Base => Array<Pin::Base>}]
|
|
199
216
|
def pin_class_hash
|
|
200
217
|
# @todo Need to support generic resolution in classify and transform_values
|
|
201
218
|
@pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
|
|
@@ -206,9 +223,12 @@ module Solargraph
|
|
|
206
223
|
@data ||= Data.new(source)
|
|
207
224
|
end
|
|
208
225
|
|
|
226
|
+
# @param pins [Array<Pin::Base>]
|
|
209
227
|
# @return [Array<Pin::Base>]
|
|
210
|
-
def convention_pins
|
|
211
|
-
|
|
228
|
+
def convention_pins= pins
|
|
229
|
+
# unmemoizing the document_symbols in case it was called from any of conventions
|
|
230
|
+
@document_symbols = nil
|
|
231
|
+
@convention_pins = pins
|
|
212
232
|
end
|
|
213
233
|
|
|
214
234
|
# @generic T
|
|
@@ -221,9 +241,8 @@ module Solargraph
|
|
|
221
241
|
position = Position.new(line, character)
|
|
222
242
|
found = nil
|
|
223
243
|
pins.each do |pin|
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
-
next if pin.is_a?(Pin::Method) && pin.attribute?
|
|
244
|
+
# A bodyless method pin covers its declaring statement's range but isn't a closure.
|
|
245
|
+
next if pin.is_a?(Pin::Method) && !pin.body?
|
|
227
246
|
found = pin if (klasses.empty? || klasses.any? do |kls|
|
|
228
247
|
pin.is_a?(kls)
|
|
229
248
|
# @sg-ignore Need to add nil check here
|
|
@@ -75,11 +75,11 @@ module Solargraph
|
|
|
75
75
|
# @todo 22: Translate to something flow sensitive typing understands
|
|
76
76
|
# @todo 3: Need a downcast here
|
|
77
77
|
#
|
|
78
|
-
# flow sensitive typing could handle (
|
|
78
|
+
# flow sensitive typing could handle (99):
|
|
79
79
|
#
|
|
80
80
|
# @todo 36: flow sensitive typing needs to handle attrs
|
|
81
81
|
# @todo 29: flow sensitive typing should be able to handle redefinition
|
|
82
|
-
# @todo
|
|
82
|
+
# @todo 21: flow sensitive typing needs to narrow down type with an if is_a? check
|
|
83
83
|
# @todo 13: Need to validate config
|
|
84
84
|
# @todo 8: flow sensitive typing should support .class == .class
|
|
85
85
|
# @todo 6: need boolish support for ? methods
|
|
@@ -113,6 +113,7 @@ module Solargraph
|
|
|
113
113
|
# @todo 1: flow sensitive typing needs to create separate ranges for postfix if
|
|
114
114
|
# @todo 1: flow sensitive typing needs to handle constants
|
|
115
115
|
# @todo 1: flow sensitive typing needs to eliminate literal from union with return if foo == :bar
|
|
116
|
+
# @todo 1: Array#flatten returns a bare Array
|
|
116
117
|
def require_all_unique_types_match_expected?
|
|
117
118
|
report?(:require_all_unique_types_match_expected, :strong)
|
|
118
119
|
end
|
|
@@ -141,6 +141,8 @@ module Solargraph
|
|
|
141
141
|
# @return [Array<Problem>]
|
|
142
142
|
def method_return_type_problems_for pin
|
|
143
143
|
return [] if pin.is_a?(Pin::MethodAlias)
|
|
144
|
+
# An unresolvable DelegatedMethod's type comes from its @!method directive, not a @return tag.
|
|
145
|
+
return [] if pin.is_a?(Pin::DelegatedMethod) && !pin.resolvable?(api_map)
|
|
144
146
|
result = []
|
|
145
147
|
declared = pin.typify(api_map).self_to_type(pin.full_context).qualify(api_map, *pin.gates)
|
|
146
148
|
if declared.undefined?
|
|
@@ -219,7 +221,7 @@ module Solargraph
|
|
|
219
221
|
params = param_details_from_stack(sig, stack)
|
|
220
222
|
if rules.require_type_tags?
|
|
221
223
|
sig.parameters.each do |par|
|
|
222
|
-
break if %i[restarg kwrestarg blockarg].include?(par.decl)
|
|
224
|
+
break if %i[restarg kwrestarg blockarg forward_args].include?(par.decl)
|
|
223
225
|
unless params[par.name]
|
|
224
226
|
if pin.attribute?
|
|
225
227
|
inferred = pin.probe(api_map).self_to_type(pin.full_context)
|
|
@@ -388,6 +390,7 @@ module Solargraph
|
|
|
388
390
|
return [] unless last_base_link.is_a?(Solargraph::Source::Chain::Call)
|
|
389
391
|
|
|
390
392
|
arguments = last_base_link.arguments
|
|
393
|
+
return [] if any_forwarded_args?(arguments.map(&:node))
|
|
391
394
|
|
|
392
395
|
pins = base.define(api_map, closure_pin, locals)
|
|
393
396
|
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/workspace.rb
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module YardMap
|
|
5
|
+
module Directives
|
|
6
|
+
# Implements YARD's @!scope directive.
|
|
7
|
+
#
|
|
8
|
+
# As described in YARD::Tags::ScopeDirective, a @!scope directive that
|
|
9
|
+
# appears in a docstring attached to a method definition applies only to
|
|
10
|
+
# that method. Anywhere else it applies to all of the methods that follow
|
|
11
|
+
# it within the namespace it was defined in.
|
|
12
|
+
#
|
|
13
|
+
# class Example
|
|
14
|
+
# # @!scope class
|
|
15
|
+
# def foo; end # => Example.foo
|
|
16
|
+
#
|
|
17
|
+
# def bar; end # => Example#bar
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# class Other
|
|
21
|
+
# # @!scope class
|
|
22
|
+
#
|
|
23
|
+
# def foo; end # => Other.foo
|
|
24
|
+
#
|
|
25
|
+
# def bar; end # => Other.bar
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
module ScopeDirective
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
VALID_SCOPES = %i[class instance].freeze
|
|
32
|
+
|
|
33
|
+
# Directives that define an object whose scope is inherited from a
|
|
34
|
+
# @!scope directive. @!parse is not one of them because the code it
|
|
35
|
+
# contains already declares the scope of everything it defines.
|
|
36
|
+
SCOPED_DIRECTIVES = %w[method attribute].freeze
|
|
37
|
+
|
|
38
|
+
# @param source [Solargraph::Source]
|
|
39
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
|
40
|
+
# @param source_position [Position]
|
|
41
|
+
# @param comment_position [Position]
|
|
42
|
+
# @param directive [YARD::Tags::Directive]
|
|
43
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
44
|
+
def process_directive source, pins, source_position, comment_position, directive
|
|
45
|
+
kind = parse_scope directive
|
|
46
|
+
return [] if kind.nil?
|
|
47
|
+
|
|
48
|
+
attached = attached_method pins, source_position
|
|
49
|
+
if attached && no_empty_lines?(source.code, comment_position.line, source_position.line)
|
|
50
|
+
attached.scope = kind
|
|
51
|
+
else
|
|
52
|
+
apply_to_namespace pins, kind, source_position
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
[]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @param directive [YARD::Tags::Directive]
|
|
59
|
+
# @return [::Symbol, nil] :class, :instance, or nil if the directive is malformed
|
|
60
|
+
def parse_scope directive
|
|
61
|
+
kind = directive.tag.text.to_s.strip.downcase.to_sym
|
|
62
|
+
VALID_SCOPES.include?(kind) ? kind : nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# True if the scope of the object defined by this directive can be set
|
|
66
|
+
# by a @!scope directive.
|
|
67
|
+
#
|
|
68
|
+
# @param directive [YARD::Tags::Directive]
|
|
69
|
+
# @return [Boolean]
|
|
70
|
+
def scopes_directive? directive
|
|
71
|
+
SCOPED_DIRECTIVES.include? directive.tag.tag_name
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The scope set by a @!scope directive that appears in the indented
|
|
75
|
+
# text of another directive:
|
|
76
|
+
#
|
|
77
|
+
# @!method foo
|
|
78
|
+
# @!scope class
|
|
79
|
+
#
|
|
80
|
+
# YARD parses the indented text of a directive with a state of its own,
|
|
81
|
+
# so a directive nested this way applies only to the object the
|
|
82
|
+
# enclosing directive defines. It never affects the objects that
|
|
83
|
+
# follow.
|
|
84
|
+
#
|
|
85
|
+
# @param directive [YARD::Tags::Directive]
|
|
86
|
+
# @return [::Symbol, nil] :class, :instance, or nil if there is none
|
|
87
|
+
def nested_scope directive
|
|
88
|
+
text = directive.tag.text.to_s
|
|
89
|
+
return nil unless text.include? '@!scope'
|
|
90
|
+
|
|
91
|
+
kind = nil
|
|
92
|
+
Solargraph::Source.parse_docstring(text).directives.each do |nested|
|
|
93
|
+
next unless nested.tag.tag_name == 'scope'
|
|
94
|
+
|
|
95
|
+
# A later directive overrides an earlier one, but an invalid value
|
|
96
|
+
# leaves the current one in place, as it does in YARD.
|
|
97
|
+
kind = parse_scope(nested) || kind
|
|
98
|
+
end
|
|
99
|
+
kind
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Set the scope of pins generated by a directive.
|
|
103
|
+
#
|
|
104
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
|
105
|
+
# @param kind [::Symbol, nil] :class or :instance; nothing happens if nil
|
|
106
|
+
# @return [void]
|
|
107
|
+
def apply_scope pins, kind
|
|
108
|
+
return if kind.nil?
|
|
109
|
+
|
|
110
|
+
# Only methods have a scope. Applying one to any other kind of pin,
|
|
111
|
+
# such as a namespace generated by @!parse, would corrupt its path.
|
|
112
|
+
pins.each { |pin| pin.scope = kind if pin.is_a?(Pin::Method) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Apply a @!scope directive from the indented text of another directive
|
|
116
|
+
# to the pins that directive generated.
|
|
117
|
+
#
|
|
118
|
+
# @param directive [YARD::Tags::Directive]
|
|
119
|
+
# @param pins [Array<Solargraph::Pin::Base>] the pins generated by the directive
|
|
120
|
+
# @return [void]
|
|
121
|
+
def apply_nested directive, pins
|
|
122
|
+
return unless scopes_directive? directive
|
|
123
|
+
|
|
124
|
+
apply_scope pins, nested_scope(directive)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Applies the scope to each method that follows the directive within
|
|
128
|
+
# the namespace the directive appears in. Methods in nested namespaces
|
|
129
|
+
# are excluded, since the directive only affects its own namespace.
|
|
130
|
+
#
|
|
131
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
|
132
|
+
# @param kind [::Symbol] :class or :instance
|
|
133
|
+
# @param source_position [Position]
|
|
134
|
+
# @return [void]
|
|
135
|
+
def apply_to_namespace pins, kind, source_position
|
|
136
|
+
namespace = namespace_at pins, source_position
|
|
137
|
+
return if namespace.nil?
|
|
138
|
+
|
|
139
|
+
pins.each do |pin|
|
|
140
|
+
next unless pin.is_a?(Pin::Method)
|
|
141
|
+
next unless pin.namespace == namespace.path
|
|
142
|
+
# @sg-ignore flow sensitive typing should narrow location after the nil check
|
|
143
|
+
next if pin.location.nil? || pin.location.range.start.line < source_position.line
|
|
144
|
+
|
|
145
|
+
pin.scope = kind
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# The method defined on the line the comment is attached to, if any.
|
|
150
|
+
#
|
|
151
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
|
152
|
+
# @param source_position [Position]
|
|
153
|
+
# @return [Pin::Method, nil]
|
|
154
|
+
def attached_method pins, source_position
|
|
155
|
+
pins.select { |pin| pin.is_a?(Pin::Method) && pin.location&.range&.contain?(source_position) }.last
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
|
159
|
+
# @param position [Position]
|
|
160
|
+
# @return [Pin::Namespace, nil]
|
|
161
|
+
def namespace_at pins, position
|
|
162
|
+
pins.select { |pin| pin.is_a?(Pin::Namespace) && pin.location&.range&.contain?(position) }.last
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @param code [String]
|
|
166
|
+
# @param line1 [Integer]
|
|
167
|
+
# @param line2 [Integer]
|
|
168
|
+
# @return [Boolean]
|
|
169
|
+
def no_empty_lines? code, line1, line2
|
|
170
|
+
lines = code.lines[line1..line2]
|
|
171
|
+
return false if lines.nil?
|
|
172
|
+
|
|
173
|
+
lines.none? { |line| line.strip.empty? }
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Solargraph
|
|
4
|
-
|
|
4
|
+
module YardMap
|
|
5
5
|
module Directives
|
|
6
6
|
autoload :AttributeDirective, 'solargraph/yard_map/directives/attribute_directive'
|
|
7
7
|
autoload :MethodDirective, 'solargraph/yard_map/directives/method_directive'
|
|
8
8
|
autoload :DomainDirective, 'solargraph/yard_map/directives/domain_directive'
|
|
9
9
|
autoload :OverrideDirective, 'solargraph/yard_map/directives/override_directive'
|
|
10
10
|
autoload :ParseDirective, 'solargraph/yard_map/directives/parse_directive'
|
|
11
|
+
autoload :ScopeDirective, 'solargraph/yard_map/directives/scope_directive'
|
|
11
12
|
autoload :VisibilityDirective, 'solargraph/yard_map/directives/visibility_directive'
|
|
12
13
|
|
|
13
14
|
# @param directive [YARD::Tags::Directive]
|
|
14
|
-
# @return [Class<AttributeDirective>, Class<MethodDirective>, Class<DomainDirective>, Class<OverrideDirective>, Class<ParseDirective>, Class<VisibilityDirective>, nil]
|
|
15
|
+
# @return [Class<AttributeDirective>, Class<MethodDirective>, Class<DomainDirective>, Class<OverrideDirective>, Class<ParseDirective>, Class<ScopeDirective>, Class<VisibilityDirective>, nil]
|
|
15
16
|
def self.for directive
|
|
16
17
|
case directive.tag.tag_name
|
|
17
18
|
when 'attribute'
|
|
@@ -24,6 +25,8 @@ module Solargraph
|
|
|
24
25
|
OverrideDirective
|
|
25
26
|
when 'parse'
|
|
26
27
|
ParseDirective
|
|
28
|
+
when 'scope'
|
|
29
|
+
ScopeDirective
|
|
27
30
|
when 'visibility'
|
|
28
31
|
VisibilityDirective
|
|
29
32
|
else # rubocop:disable Style/EmptyElse
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Solargraph
|
|
4
|
-
|
|
4
|
+
module YardMap
|
|
5
5
|
class Macro
|
|
6
|
-
PROCESSABLE_DIRECTIVES = %w[method attribute parse].freeze
|
|
6
|
+
PROCESSABLE_DIRECTIVES = %w[method attribute parse scope].freeze
|
|
7
|
+
|
|
8
|
+
# Directives whose text is a value rather than a definition. The comments
|
|
9
|
+
# attached to the macro's call site belong to the objects the macro
|
|
10
|
+
# generates, but adding them to one of these directives would invalidate
|
|
11
|
+
# its content.
|
|
12
|
+
VALUE_DIRECTIVES = %w[parse scope].freeze
|
|
13
|
+
|
|
14
|
+
# Directives that define an object capable of owning @overload tags.
|
|
15
|
+
OVERLOAD_OWNERS = %w[method attribute parse].freeze
|
|
16
|
+
|
|
17
|
+
# The directive used to generate a pin for the @overload tags a macro
|
|
18
|
+
# declares without an owning @!method directive. Its arguments are
|
|
19
|
+
# represented by (...) so that any of the overloads remains valid.
|
|
20
|
+
OVERLOAD_METHOD_DIRECTIVE = '@!method $1(...)'
|
|
21
|
+
|
|
22
|
+
# An @overload tag that starts a line of a macro's text.
|
|
23
|
+
OVERLOAD_TAG_LINE = /^\s*@overload(\s|$)/
|
|
7
24
|
|
|
8
25
|
class << self
|
|
9
26
|
# @param directive [YARD::Tags::Directive]
|
|
@@ -73,13 +90,34 @@ module Solargraph
|
|
|
73
90
|
# @return [Array<Pin::Base>]
|
|
74
91
|
def generate_pins_from chain, pin, source_map
|
|
75
92
|
call_location = Solargraph::Location.from_node(chain.node)
|
|
93
|
+
return [] unless call_location
|
|
94
|
+
|
|
95
|
+
# A @!scope directive in a macro applies to the objects the macro
|
|
96
|
+
# generates after it, the same way it applies to the objects that
|
|
97
|
+
# follow it in a namespace. Its effect ends with the macro.
|
|
98
|
+
#
|
|
99
|
+
# @type [::Symbol, nil]
|
|
100
|
+
inherited_scope = nil
|
|
101
|
+
|
|
76
102
|
# @param generated_pins [Array<Pin::Base>]
|
|
77
103
|
generate_yardoc_from(chain, source_map).reduce([]) do |generated_pins, directive|
|
|
104
|
+
# @sg-ignore flow sensitive typing confuses this block variable with the #directive attr reader
|
|
105
|
+
if directive.tag.tag_name == 'scope'
|
|
106
|
+
inherited_scope = Directives::ScopeDirective.parse_scope(directive) || inherited_scope
|
|
107
|
+
next generated_pins
|
|
108
|
+
end
|
|
78
109
|
directive_processor = YardMap::Directives.for(directive)
|
|
79
|
-
next generated_pins unless directive_processor
|
|
80
|
-
|
|
110
|
+
next generated_pins unless directive_processor
|
|
111
|
+
new_pins = directive_processor.process_directive(
|
|
81
112
|
source_map.source, source_map.pins, call_location.range.start, call_location.range.start, directive
|
|
82
113
|
)
|
|
114
|
+
if Directives::ScopeDirective.scopes_directive?(directive)
|
|
115
|
+
# A @!scope directive nested in another directive's text applies
|
|
116
|
+
# only to the object that directive defines.
|
|
117
|
+
scope = Directives::ScopeDirective.nested_scope(directive) || inherited_scope
|
|
118
|
+
Directives::ScopeDirective.apply_scope new_pins, scope
|
|
119
|
+
end
|
|
120
|
+
generated_pins + new_pins
|
|
83
121
|
end
|
|
84
122
|
end
|
|
85
123
|
|
|
@@ -96,18 +134,59 @@ module Solargraph
|
|
|
96
134
|
code = source_map.source.code_for(chain.node)
|
|
97
135
|
expanded_comment = macro_object.expand([name, *values], code)
|
|
98
136
|
.gsub(/\n(?!@!|\s)/, "\n ")
|
|
99
|
-
|
|
137
|
+
parsed_docstring = Solargraph::Source.parse_docstring(expanded_comment)
|
|
138
|
+
directives = parsed_docstring.directives.select do |directive|
|
|
100
139
|
PROCESSABLE_DIRECTIVES.include?(directive.tag.tag_name)
|
|
101
140
|
end
|
|
141
|
+
# A macro can document the methods it generates with bare @overload
|
|
142
|
+
# tags instead of wrapping them in a @!method directive. Those overloads
|
|
143
|
+
# have no pin to attach to and would otherwise be discarded, so
|
|
144
|
+
# generate the pin they describe.
|
|
145
|
+
if declares_overloads? && directives.none? { |directive| OVERLOAD_OWNERS.include?(directive.tag.tag_name) }
|
|
146
|
+
directives += generate_overload_directives([name, *values], code)
|
|
147
|
+
end
|
|
102
148
|
directives.each do |directive|
|
|
149
|
+
next if VALUE_DIRECTIVES.include? directive.tag.tag_name
|
|
150
|
+
|
|
103
151
|
# @sg-ignore chain.node is assumed to exist
|
|
104
152
|
comments = source_map.source.comments_for(chain.node)
|
|
105
|
-
if comments&.length&.positive?
|
|
153
|
+
if comments&.length&.positive?
|
|
106
154
|
directive.tag.text += "\n#{comments}"
|
|
107
155
|
end
|
|
108
156
|
end
|
|
109
157
|
directives
|
|
110
158
|
end
|
|
159
|
+
|
|
160
|
+
# True if the macro declares @overload tags. The tags are read from the
|
|
161
|
+
# macro's text and not from its parsed docstring because the indentation
|
|
162
|
+
# a macro's content ends up with can nest the tags inside other objects.
|
|
163
|
+
#
|
|
164
|
+
# @return [Boolean]
|
|
165
|
+
def declares_overloads?
|
|
166
|
+
text.match?(OVERLOAD_TAG_LINE)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Generates the @!method directive for a macro's bare @overload tags. The
|
|
170
|
+
# pin takes the name the macro generates, that is, the pin a
|
|
171
|
+
# @!method $1(...) directive would produce, and keeps the overloads in
|
|
172
|
+
# its comments.
|
|
173
|
+
#
|
|
174
|
+
# The macro's unprocessed text is used here and not its macro data. The
|
|
175
|
+
# data is re-indented for @! directives, which flattens the nesting that
|
|
176
|
+
# keeps a @param attached to the @overload it describes.
|
|
177
|
+
#
|
|
178
|
+
# @param call_params [Array<String>]
|
|
179
|
+
# @param code [String]
|
|
180
|
+
# @return [Array<YARD::Tags::Directive>]
|
|
181
|
+
def generate_overload_directives call_params, code
|
|
182
|
+
body = text.each_line.map { |line| " #{line}" }.join
|
|
183
|
+
expanded = YARD::CodeObjects::MacroObject.expand(
|
|
184
|
+
"#{OVERLOAD_METHOD_DIRECTIVE}\n#{body}", call_params, code
|
|
185
|
+
)
|
|
186
|
+
Solargraph::Source.parse_docstring(expanded).directives.select do |directive|
|
|
187
|
+
directive.tag.tag_name == 'method'
|
|
188
|
+
end
|
|
189
|
+
end
|
|
111
190
|
end
|
|
112
191
|
end
|
|
113
192
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Solargraph
|
|
4
|
-
|
|
4
|
+
module YardMap
|
|
5
5
|
class Mapper
|
|
6
6
|
autoload :ToMethod, 'solargraph/yard_map/mapper/to_method'
|
|
7
7
|
autoload :ToNamespace, 'solargraph/yard_map/mapper/to_namespace'
|
|
@@ -33,7 +33,7 @@ module Solargraph
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
35
|
def core_store
|
|
36
|
-
@core_store ||= ApiMap::Store.new(RbsMap::
|
|
36
|
+
@core_store ||= ApiMap::Store.new(RbsMap::Core.new.pins)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# @param code_object [YARD::CodeObjects::Base]
|
data/lib/solargraph/yard_map.rb
CHANGED