solargraph 0.56.0 → 0.57.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 +125 -0
- data/.github/workflows/plugins.yml +148 -6
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +5 -2
- data/.gitignore +5 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +2627 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +56 -1
- data/README.md +8 -4
- data/Rakefile +125 -13
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +218 -0
- data/lib/solargraph/api_map/index.rb +20 -26
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +126 -18
- data/lib/solargraph/api_map.rb +212 -234
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +1 -0
- data/lib/solargraph/complex_type/unique_type.rb +7 -7
- data/lib/solargraph/complex_type.rb +5 -1
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +17 -0
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
- data/lib/solargraph/convention/struct_definition.rb +87 -24
- data/lib/solargraph/convention.rb +32 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +48 -17
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +17 -11
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +3 -0
- data/lib/solargraph/language_server/host.rb +2 -1
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/progress.rb +8 -0
- data/lib/solargraph/language_server/request.rb +1 -0
- data/lib/solargraph/library.rb +47 -30
- data/lib/solargraph/location.rb +2 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -4
- data/lib/solargraph/parser/node_methods.rb +2 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +24 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +1 -1
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +65 -8
- data/lib/solargraph/pin/base_variable.rb +1 -2
- data/lib/solargraph/pin/callable.rb +9 -0
- data/lib/solargraph/pin/closure.rb +2 -0
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +1 -0
- data/lib/solargraph/pin/local_variable.rb +4 -1
- data/lib/solargraph/pin/method.rb +12 -7
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +18 -8
- data/lib/solargraph/pin/proxy_type.rb +1 -0
- data/lib/solargraph/pin/reference/override.rb +15 -1
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +26 -0
- data/lib/solargraph/pin/search.rb +3 -1
- data/lib/solargraph/pin/signature.rb +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +2 -0
- data/lib/solargraph/range.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +47 -18
- data/lib/solargraph/rbs_map/core_map.rb +3 -0
- data/lib/solargraph/rbs_map.rb +15 -2
- data/lib/solargraph/shell.rb +3 -0
- data/lib/solargraph/source/chain/link.rb +10 -1
- data/lib/solargraph/source/chain.rb +9 -2
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +1 -1
- data/lib/solargraph/source.rb +5 -2
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +4 -2
- data/lib/solargraph/source_map.rb +21 -14
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +8 -0
- data/lib/solargraph/type_checker.rb +173 -120
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +24 -48
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +3 -8
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +7 -7
- data/lib/solargraph/yardoc.rb +18 -3
- data/lib/solargraph.rb +15 -0
- data/rbs/fills/tuple.rbs +2 -3
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +14 -4
- metadata +128 -11
- data/lib/.rubocop.yml +0 -22
data/lib/solargraph/bench.rb
CHANGED
@@ -49,11 +49,7 @@ module Solargraph
|
|
49
49
|
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
50
50
|
if parameters_type == :hash
|
51
51
|
raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
52
|
-
# @todo should be able to resolve map; both types have it
|
53
|
-
# with same return type
|
54
|
-
# @sg-ignore
|
55
52
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
56
|
-
# @sg-ignore
|
57
53
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
58
54
|
elsif parameters_type == :list && name == 'Hash'
|
59
55
|
# Treat Hash<A, B> as Hash{A => B}
|
@@ -105,6 +101,7 @@ module Solargraph
|
|
105
101
|
tag
|
106
102
|
end
|
107
103
|
|
104
|
+
# @return [self]
|
108
105
|
def simplify_literals
|
109
106
|
transform do |t|
|
110
107
|
next t unless t.literal?
|
@@ -116,10 +113,12 @@ module Solargraph
|
|
116
113
|
non_literal_name != name
|
117
114
|
end
|
118
115
|
|
116
|
+
# @return [String]
|
119
117
|
def non_literal_name
|
120
118
|
@non_literal_name ||= determine_non_literal_name
|
121
119
|
end
|
122
120
|
|
121
|
+
# @return [String]
|
123
122
|
def determine_non_literal_name
|
124
123
|
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
125
124
|
#
|
@@ -171,6 +170,7 @@ module Solargraph
|
|
171
170
|
end
|
172
171
|
end
|
173
172
|
|
173
|
+
# @return [String]
|
174
174
|
def desc
|
175
175
|
rooted_tags
|
176
176
|
end
|
@@ -255,7 +255,7 @@ module Solargraph
|
|
255
255
|
|
256
256
|
# @param generics_to_resolve [Enumerable<String>]
|
257
257
|
# @param context_type [UniqueType, nil]
|
258
|
-
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
258
|
+
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
259
259
|
# @return [UniqueType, ComplexType]
|
260
260
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
261
261
|
if name == ComplexType::GENERIC_TAG_NAME
|
@@ -353,9 +353,9 @@ module Solargraph
|
|
353
353
|
|
354
354
|
# @param new_name [String, nil]
|
355
355
|
# @param make_rooted [Boolean, nil]
|
356
|
-
# @param new_key_types [Array<
|
356
|
+
# @param new_key_types [Array<ComplexType>, nil]
|
357
357
|
# @param rooted [Boolean, nil]
|
358
|
-
# @param new_subtypes [Array<
|
358
|
+
# @param new_subtypes [Array<ComplexType>, nil]
|
359
359
|
# @return [self]
|
360
360
|
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
361
361
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
@@ -155,10 +155,12 @@ module Solargraph
|
|
155
155
|
map(&:tag).join(', ')
|
156
156
|
end
|
157
157
|
|
158
|
+
# @return [String]
|
158
159
|
def tags
|
159
160
|
map(&:tag).join(', ')
|
160
161
|
end
|
161
162
|
|
163
|
+
# @return [String]
|
162
164
|
def simple_tags
|
163
165
|
simplify_literals.tags
|
164
166
|
end
|
@@ -172,10 +174,12 @@ module Solargraph
|
|
172
174
|
ComplexType.new(items.map(&:downcast_to_literal_if_possible))
|
173
175
|
end
|
174
176
|
|
177
|
+
# @return [String]
|
175
178
|
def desc
|
176
179
|
rooted_tags
|
177
180
|
end
|
178
181
|
|
182
|
+
# @return [String]
|
179
183
|
def rooted_tags
|
180
184
|
map(&:rooted_tag).join(', ')
|
181
185
|
end
|
@@ -200,6 +204,7 @@ module Solargraph
|
|
200
204
|
any?(&:generic?)
|
201
205
|
end
|
202
206
|
|
207
|
+
# @return [self]
|
203
208
|
def simplify_literals
|
204
209
|
ComplexType.new(map(&:simplify_literals))
|
205
210
|
end
|
@@ -299,7 +304,6 @@ module Solargraph
|
|
299
304
|
# # @todo Need ability to use a literal true as a type below
|
300
305
|
# # @param partial [Boolean] True if the string is part of a another type
|
301
306
|
# # @return [Array<UniqueType>]
|
302
|
-
# @sg-ignore
|
303
307
|
# @todo To be able to select the right signature above,
|
304
308
|
# Chain::Call needs to know the decl type (:arg, :optarg,
|
305
309
|
# :kwarg, etc) of the arguments given, instead of just having
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
# ActiveSupport::Concern is syntactic sugar for a common
|
6
|
+
# pattern to include class methods while mixing-in a Module
|
7
|
+
# See https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
|
8
|
+
class ActiveSupportConcern < Base
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
# @return [Array<Pin::Base>]
|
12
|
+
attr_reader :pins
|
13
|
+
|
14
|
+
# @param api_map [ApiMap]
|
15
|
+
# @param rooted_tag [String]
|
16
|
+
# @param scope [Symbol] :class or :instance
|
17
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
18
|
+
# @param deep [Boolean] whether to include methods from included modules
|
19
|
+
# @param skip [Set<String>]
|
20
|
+
# @param _no_core [Boolean]n whether to skip core methods
|
21
|
+
def object api_map, rooted_tag, scope, visibility, deep, skip, _no_core
|
22
|
+
moo = ObjectProcessor.new(api_map, rooted_tag, scope, visibility, deep, skip)
|
23
|
+
moo.environ
|
24
|
+
end
|
25
|
+
|
26
|
+
# yard-activesupport-concern pulls methods inside
|
27
|
+
# 'class_methods' blocks into main class visible from YARD
|
28
|
+
#
|
29
|
+
# @param _doc_map [DocMap]
|
30
|
+
def global _doc_map
|
31
|
+
Environ.new(yard_plugins: ['activesupport-concern'])
|
32
|
+
end
|
33
|
+
|
34
|
+
# Process an object to add any class methods brought in via
|
35
|
+
# ActiveSupport::Concern
|
36
|
+
class ObjectProcessor
|
37
|
+
include Logging
|
38
|
+
|
39
|
+
attr_reader :environ
|
40
|
+
|
41
|
+
# @param api_map [ApiMap]
|
42
|
+
# @param rooted_tag [String] the tag of the class or module being processed
|
43
|
+
# @param scope [Symbol] :class or :instance
|
44
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
45
|
+
# @param deep [Boolean] whether to include methods from included modules
|
46
|
+
# @param skip [Set<String>] a set of tags to skip
|
47
|
+
def initialize api_map, rooted_tag, scope, visibility, deep, skip
|
48
|
+
@api_map = api_map
|
49
|
+
@rooted_tag = rooted_tag
|
50
|
+
@scope = scope
|
51
|
+
@visibility = visibility
|
52
|
+
@deep = deep
|
53
|
+
@skip = skip
|
54
|
+
|
55
|
+
@environ = Environ.new
|
56
|
+
return unless scope == :class
|
57
|
+
|
58
|
+
@rooted_type = ComplexType.parse(rooted_tag).force_rooted
|
59
|
+
@fqns = rooted_type.namespace
|
60
|
+
@namespace_pin = api_map.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
61
|
+
|
62
|
+
api_map.get_includes(fqns).reverse.each do |include_tag|
|
63
|
+
process_include include_tag
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
attr_reader :api_map, :rooted_tag, :rooted_type, :scope,
|
70
|
+
:visibility, :deep, :skip, :namespace_pin,
|
71
|
+
:fqns
|
72
|
+
|
73
|
+
# @param include_tag [Pin::Reference::Include] the include reference pin
|
74
|
+
#
|
75
|
+
# @return [void]
|
76
|
+
def process_include include_tag
|
77
|
+
rooted_include_tag = api_map.dereference(include_tag)
|
78
|
+
return if rooted_include_tag.nil?
|
79
|
+
logger.debug do
|
80
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
81
|
+
"Handling class include include_tag=#{include_tag}"
|
82
|
+
end
|
83
|
+
module_extends = api_map.get_extends(rooted_include_tag).map(&:parametrized_tag).map(&:to_s)
|
84
|
+
logger.debug do
|
85
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
86
|
+
"found module extends of #{rooted_include_tag}: #{module_extends}"
|
87
|
+
end
|
88
|
+
return unless module_extends.include? 'ActiveSupport::Concern'
|
89
|
+
included_class_pins = api_map.inner_get_methods_from_reference(rooted_include_tag, namespace_pin, rooted_type,
|
90
|
+
:class, visibility, deep, skip, true)
|
91
|
+
logger.debug do
|
92
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
93
|
+
"Found #{included_class_pins.length} inluded class methods for #{rooted_include_tag}"
|
94
|
+
end
|
95
|
+
environ.pins.concat included_class_pins
|
96
|
+
# another pattern is to put class methods inside a submodule
|
97
|
+
classmethods_include_tag = "#{rooted_include_tag}::ClassMethods"
|
98
|
+
included_classmethods_pins =
|
99
|
+
api_map.inner_get_methods_from_reference(classmethods_include_tag, namespace_pin, rooted_type,
|
100
|
+
:instance, visibility, deep, skip, true)
|
101
|
+
logger.debug do
|
102
|
+
"ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \
|
103
|
+
"Found #{included_classmethods_pins.length} included classmethod " \
|
104
|
+
"class methods for #{classmethods_include_tag}"
|
105
|
+
end
|
106
|
+
environ.pins.concat included_classmethods_pins
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -28,6 +28,23 @@ module Solargraph
|
|
28
28
|
def global doc_map
|
29
29
|
EMPTY_ENVIRON
|
30
30
|
end
|
31
|
+
|
32
|
+
# Provides any additional method pins based on e the described object.
|
33
|
+
#
|
34
|
+
# @param api_map [ApiMap]
|
35
|
+
# @param rooted_tag [String] A fully qualified namespace, with
|
36
|
+
# generic parameter values if applicable
|
37
|
+
# @param scope [Symbol] :class or :instance
|
38
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
39
|
+
# @param deep [Boolean]
|
40
|
+
# @param skip [Set<String>]
|
41
|
+
# @param no_core [Boolean] Skip core classes if true
|
42
|
+
#
|
43
|
+
# @return [Environ]
|
44
|
+
def object api_map, rooted_tag, scope, visibility,
|
45
|
+
deep, skip, no_core
|
46
|
+
EMPTY_ENVIRON
|
47
|
+
end
|
31
48
|
end
|
32
49
|
end
|
33
50
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module DataDefinition
|
6
|
+
# A node wrapper for a Data definition via const assignment.
|
7
|
+
# @example
|
8
|
+
# MyData = Data.new(:bar, :baz) do
|
9
|
+
# def foo
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
class DataAssignmentNode < DataDefintionNode
|
13
|
+
class << self
|
14
|
+
# @example
|
15
|
+
# s(:casgn, nil, :Foo,
|
16
|
+
# s(:block,
|
17
|
+
# s(:send,
|
18
|
+
# s(:const, nil, :Data), :define,
|
19
|
+
# s(:sym, :bar),
|
20
|
+
# s(:sym, :baz)),
|
21
|
+
# s(:args),
|
22
|
+
# s(:def, :foo,
|
23
|
+
# s(:args),
|
24
|
+
# s(:send, nil, :bar))))
|
25
|
+
# @param node [::Parser::AST::Node]
|
26
|
+
def match?(node)
|
27
|
+
return false unless node&.type == :casgn
|
28
|
+
return false if node.children[2].nil?
|
29
|
+
|
30
|
+
data_node = if node.children[2].type == :block
|
31
|
+
node.children[2].children[0]
|
32
|
+
else
|
33
|
+
node.children[2]
|
34
|
+
end
|
35
|
+
|
36
|
+
data_definition_node?(data_node)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def class_name
|
41
|
+
if node.children[0]
|
42
|
+
Parser::NodeMethods.unpack_name(node.children[0]) + "::#{node.children[1]}"
|
43
|
+
else
|
44
|
+
node.children[1].to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# @return [Parser::AST::Node]
|
51
|
+
def data_node
|
52
|
+
if node.children[2].type == :block
|
53
|
+
node.children[2].children[0]
|
54
|
+
else
|
55
|
+
node.children[2]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module DataDefinition
|
6
|
+
# A node wrapper for a Data definition via inheritance.
|
7
|
+
# @example
|
8
|
+
# class MyData < Data.new(:bar, :baz)
|
9
|
+
# def foo
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
class DataDefintionNode
|
13
|
+
class << self
|
14
|
+
# @example
|
15
|
+
# s(:class,
|
16
|
+
# s(:const, nil, :Foo),
|
17
|
+
# s(:send,
|
18
|
+
# s(:const, nil, :Data), :define,
|
19
|
+
# s(:sym, :bar),
|
20
|
+
# s(:sym, :baz)),
|
21
|
+
# s(:hash,
|
22
|
+
# s(:pair,
|
23
|
+
# s(:sym, :keyword_init),
|
24
|
+
# s(:true)))),
|
25
|
+
# s(:def, :foo,
|
26
|
+
# s(:args),
|
27
|
+
# s(:send, nil, :bar)))
|
28
|
+
#
|
29
|
+
# @param node [Parser::AST::Node]
|
30
|
+
def match?(node)
|
31
|
+
return false unless node&.type == :class
|
32
|
+
|
33
|
+
data_definition_node?(node.children[1])
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @param data_node [Parser::AST::Node]
|
39
|
+
# @return [Boolean]
|
40
|
+
def data_definition_node?(data_node)
|
41
|
+
return false unless data_node.is_a?(::Parser::AST::Node)
|
42
|
+
return false unless data_node&.type == :send
|
43
|
+
return false unless data_node.children[0]&.type == :const
|
44
|
+
return false unless data_node.children[0].children[1] == :Data
|
45
|
+
return false unless data_node.children[1] == :define
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param node [Parser::AST::Node]
|
52
|
+
def initialize(node)
|
53
|
+
@node = node
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def class_name
|
58
|
+
Parser::NodeMethods.unpack_name(node)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Array<Array(Parser::AST::Node, String)>]
|
62
|
+
def attributes
|
63
|
+
data_attribute_nodes.map do |data_def_param|
|
64
|
+
next unless data_def_param.type == :sym
|
65
|
+
[data_def_param, data_def_param.children[0].to_s]
|
66
|
+
end.compact
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Parser::AST::Node]
|
70
|
+
def body_node
|
71
|
+
node.children[2]
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @return [Parser::AST::Node]
|
77
|
+
attr_reader :node
|
78
|
+
|
79
|
+
# @return [Parser::AST::Node]
|
80
|
+
def data_node
|
81
|
+
node.children[1]
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array<Parser::AST::Node>]
|
85
|
+
def data_attribute_nodes
|
86
|
+
data_node.children[2..-1]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
module DataDefinition
|
6
|
+
autoload :DataDefintionNode, 'solargraph/convention/data_definition/data_definition_node'
|
7
|
+
autoload :DataAssignmentNode, 'solargraph/convention/data_definition/data_assignment_node'
|
8
|
+
|
9
|
+
module NodeProcessors
|
10
|
+
class DataNode < Parser::NodeProcessor::Base
|
11
|
+
# @return [Boolean] continue processing the next processor of the same node.
|
12
|
+
def process
|
13
|
+
return true if data_definition_node.nil?
|
14
|
+
|
15
|
+
loc = get_node_location(node)
|
16
|
+
nspin = Solargraph::Pin::Namespace.new(
|
17
|
+
type: :class,
|
18
|
+
location: loc,
|
19
|
+
closure: region.closure,
|
20
|
+
name: data_definition_node.class_name,
|
21
|
+
comments: comments_for(node),
|
22
|
+
visibility: :public,
|
23
|
+
gates: region.closure.gates.freeze
|
24
|
+
)
|
25
|
+
pins.push nspin
|
26
|
+
|
27
|
+
# define initialize method
|
28
|
+
initialize_method_pin = Pin::Method.new(
|
29
|
+
name: 'initialize',
|
30
|
+
parameters: [],
|
31
|
+
scope: :instance,
|
32
|
+
location: get_node_location(node),
|
33
|
+
closure: nspin,
|
34
|
+
visibility: :private,
|
35
|
+
comments: comments_for(node)
|
36
|
+
)
|
37
|
+
|
38
|
+
# @todo Support both arg and kwarg initializers for Data.define
|
39
|
+
# Solargraph::SourceMap::Clip#complete_keyword_parameters does not seem to currently take into account [Pin::Method#signatures] hence we only one for :kwarg
|
40
|
+
pins.push initialize_method_pin
|
41
|
+
|
42
|
+
data_definition_node.attributes.map do |attribute_node, attribute_name|
|
43
|
+
initialize_method_pin.parameters.push(
|
44
|
+
Pin::Parameter.new(
|
45
|
+
name: attribute_name,
|
46
|
+
decl: :kwarg,
|
47
|
+
location: get_node_location(attribute_node),
|
48
|
+
closure: initialize_method_pin
|
49
|
+
)
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
# define attribute readers and instance variables
|
54
|
+
data_definition_node.attributes.each do |attribute_node, attribute_name|
|
55
|
+
name = attribute_name.to_s
|
56
|
+
method_pin = Pin::Method.new(
|
57
|
+
name: name,
|
58
|
+
parameters: [],
|
59
|
+
scope: :instance,
|
60
|
+
location: get_node_location(attribute_node),
|
61
|
+
closure: nspin,
|
62
|
+
comments: attribute_comments(attribute_node, attribute_name),
|
63
|
+
visibility: :public
|
64
|
+
)
|
65
|
+
|
66
|
+
pins.push method_pin
|
67
|
+
|
68
|
+
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
|
69
|
+
closure: method_pin,
|
70
|
+
location: get_node_location(attribute_node),
|
71
|
+
comments: attribute_comments(attribute_node, attribute_name))
|
72
|
+
end
|
73
|
+
|
74
|
+
process_children region.update(closure: nspin, visibility: :public)
|
75
|
+
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @return [DataDefintionNode, nil]
|
82
|
+
def data_definition_node
|
83
|
+
@data_definition_node ||= if DataDefintionNode.match?(node)
|
84
|
+
DataDefintionNode.new(node)
|
85
|
+
elsif DataAssignmentNode.match?(node)
|
86
|
+
DataAssignmentNode.new(node)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param attribute_node [Parser::AST::Node]
|
91
|
+
# @param attribute_name [String]
|
92
|
+
# @return [String, nil]
|
93
|
+
def attribute_comments(attribute_node, attribute_name)
|
94
|
+
data_comments = comments_for(attribute_node)
|
95
|
+
return if data_comments.nil? || data_comments.empty?
|
96
|
+
|
97
|
+
data_comments.split("\n").find do |row|
|
98
|
+
row.include?(attribute_name)
|
99
|
+
end&.gsub('@param', '@return')&.gsub(attribute_name, '')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -4,7 +4,7 @@ module Solargraph
|
|
4
4
|
module Convention
|
5
5
|
class Gemspec < Base
|
6
6
|
def local source_map
|
7
|
-
return EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
|
7
|
+
return Convention::Base::EMPTY_ENVIRON unless File.basename(source_map.filename).end_with?('.gemspec')
|
8
8
|
@environ ||= Environ.new(
|
9
9
|
requires: ['rubygems'],
|
10
10
|
pins: [
|
@@ -12,7 +12,8 @@ module Solargraph
|
|
12
12
|
'Gem::Specification.new',
|
13
13
|
%(
|
14
14
|
@yieldparam [self]
|
15
|
-
)
|
15
|
+
),
|
16
|
+
source: :gemspec
|
16
17
|
)
|
17
18
|
]
|
18
19
|
)
|
@@ -25,7 +25,9 @@ module Solargraph
|
|
25
25
|
# s(:def, :foo,
|
26
26
|
# s(:args),
|
27
27
|
# s(:send, nil, :bar)))
|
28
|
-
|
28
|
+
#
|
29
|
+
# @param node [Parser::AST::Node]
|
30
|
+
def match?(node)
|
29
31
|
return false unless node&.type == :class
|
30
32
|
|
31
33
|
struct_definition_node?(node.children[1])
|
@@ -46,7 +48,7 @@ module Solargraph
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
# @
|
51
|
+
# @param node [Parser::AST::Node]
|
50
52
|
def initialize(node)
|
51
53
|
@node = node
|
52
54
|
end
|