solargraph 0.58.1 → 0.59.0.dev.1

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.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop_todo.yml +27 -49
  8. data/README.md +3 -3
  9. data/Rakefile +1 -0
  10. data/lib/solargraph/api_map/cache.rb +110 -110
  11. data/lib/solargraph/api_map/constants.rb +289 -279
  12. data/lib/solargraph/api_map/index.rb +204 -193
  13. data/lib/solargraph/api_map/source_to_yard.rb +109 -97
  14. data/lib/solargraph/api_map/store.rb +387 -384
  15. data/lib/solargraph/api_map.rb +1000 -945
  16. data/lib/solargraph/complex_type/conformance.rb +176 -0
  17. data/lib/solargraph/complex_type/type_methods.rb +242 -228
  18. data/lib/solargraph/complex_type/unique_type.rb +632 -482
  19. data/lib/solargraph/complex_type.rb +549 -444
  20. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  21. data/lib/solargraph/convention/data_definition.rb +108 -105
  22. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  23. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  24. data/lib/solargraph/convention/struct_definition.rb +168 -164
  25. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  26. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  27. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  28. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  29. data/lib/solargraph/doc_map.rb +200 -439
  30. data/lib/solargraph/equality.rb +34 -34
  31. data/lib/solargraph/gem_pins.rb +97 -98
  32. data/lib/solargraph/language_server/host/dispatch.rb +131 -130
  33. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  34. data/lib/solargraph/language_server/host/sources.rb +100 -99
  35. data/lib/solargraph/language_server/host.rb +883 -878
  36. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
  37. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  38. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  39. data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
  40. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
  41. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  42. data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
  43. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  44. data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
  46. data/lib/solargraph/library.rb +729 -683
  47. data/lib/solargraph/location.rb +87 -82
  48. data/lib/solargraph/logging.rb +57 -37
  49. data/lib/solargraph/parser/comment_ripper.rb +76 -69
  50. data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
  51. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  52. data/lib/solargraph/parser/node_processor.rb +63 -62
  53. data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
  54. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  55. data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
  56. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  57. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  58. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  59. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  60. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  61. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  62. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
  63. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  64. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  65. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  66. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  68. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  69. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
  70. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
  71. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  72. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  73. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  74. data/lib/solargraph/parser/region.rb +75 -69
  75. data/lib/solargraph/parser/snippet.rb +17 -17
  76. data/lib/solargraph/pin/base.rb +761 -729
  77. data/lib/solargraph/pin/base_variable.rb +418 -126
  78. data/lib/solargraph/pin/block.rb +126 -104
  79. data/lib/solargraph/pin/breakable.rb +13 -9
  80. data/lib/solargraph/pin/callable.rb +278 -231
  81. data/lib/solargraph/pin/closure.rb +68 -72
  82. data/lib/solargraph/pin/common.rb +94 -79
  83. data/lib/solargraph/pin/compound_statement.rb +55 -0
  84. data/lib/solargraph/pin/conversions.rb +124 -123
  85. data/lib/solargraph/pin/delegated_method.rb +131 -120
  86. data/lib/solargraph/pin/documenting.rb +115 -114
  87. data/lib/solargraph/pin/instance_variable.rb +38 -34
  88. data/lib/solargraph/pin/keyword.rb +16 -20
  89. data/lib/solargraph/pin/local_variable.rb +31 -75
  90. data/lib/solargraph/pin/method.rb +720 -672
  91. data/lib/solargraph/pin/method_alias.rb +42 -34
  92. data/lib/solargraph/pin/namespace.rb +121 -115
  93. data/lib/solargraph/pin/parameter.rb +338 -275
  94. data/lib/solargraph/pin/proxy_type.rb +40 -39
  95. data/lib/solargraph/pin/reference/override.rb +47 -47
  96. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  97. data/lib/solargraph/pin/reference.rb +41 -39
  98. data/lib/solargraph/pin/search.rb +62 -61
  99. data/lib/solargraph/pin/signature.rb +69 -61
  100. data/lib/solargraph/pin/symbol.rb +53 -53
  101. data/lib/solargraph/pin/until.rb +18 -18
  102. data/lib/solargraph/pin/while.rb +18 -18
  103. data/lib/solargraph/pin.rb +46 -44
  104. data/lib/solargraph/pin_cache.rb +665 -245
  105. data/lib/solargraph/position.rb +118 -119
  106. data/lib/solargraph/range.rb +112 -112
  107. data/lib/solargraph/rbs_map/conversions.rb +846 -823
  108. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  109. data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
  110. data/lib/solargraph/rbs_map.rb +217 -163
  111. data/lib/solargraph/shell.rb +397 -352
  112. data/lib/solargraph/source/chain/call.rb +372 -337
  113. data/lib/solargraph/source/chain/constant.rb +28 -26
  114. data/lib/solargraph/source/chain/hash.rb +35 -34
  115. data/lib/solargraph/source/chain/if.rb +29 -28
  116. data/lib/solargraph/source/chain/instance_variable.rb +34 -13
  117. data/lib/solargraph/source/chain/literal.rb +53 -48
  118. data/lib/solargraph/source/chain/or.rb +31 -23
  119. data/lib/solargraph/source/chain.rb +294 -291
  120. data/lib/solargraph/source/change.rb +89 -82
  121. data/lib/solargraph/source/cursor.rb +172 -166
  122. data/lib/solargraph/source/source_chainer.rb +204 -194
  123. data/lib/solargraph/source/updater.rb +59 -55
  124. data/lib/solargraph/source.rb +524 -498
  125. data/lib/solargraph/source_map/clip.rb +237 -226
  126. data/lib/solargraph/source_map/data.rb +37 -34
  127. data/lib/solargraph/source_map/mapper.rb +282 -259
  128. data/lib/solargraph/source_map.rb +220 -212
  129. data/lib/solargraph/type_checker/problem.rb +34 -32
  130. data/lib/solargraph/type_checker/rules.rb +157 -84
  131. data/lib/solargraph/type_checker.rb +895 -814
  132. data/lib/solargraph/version.rb +1 -1
  133. data/lib/solargraph/workspace/config.rb +257 -255
  134. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  135. data/lib/solargraph/workspace/require_paths.rb +98 -97
  136. data/lib/solargraph/workspace.rb +362 -220
  137. data/lib/solargraph/yard_map/helpers.rb +45 -44
  138. data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
  139. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  140. data/lib/solargraph/yard_map/mapper.rb +84 -79
  141. data/lib/solargraph/yardoc.rb +97 -87
  142. data/lib/solargraph.rb +126 -105
  143. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  144. data/rbs/fills/tuple/tuple.rbs +28 -0
  145. data/rbs/shims/ast/0/node.rbs +5 -0
  146. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  147. data/rbs_collection.yaml +1 -1
  148. data/solargraph.gemspec +2 -1
  149. metadata +22 -17
  150. data/lib/solargraph/type_checker/checks.rb +0 -124
  151. data/lib/solargraph/type_checker/param_def.rb +0 -37
  152. data/lib/solargraph/yard_map/to_method.rb +0 -89
  153. data/sig/shims/ast/0/node.rbs +0 -5
  154. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  155. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  156. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  157. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  158. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  159. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  160. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  161. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  162. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,102 +1,103 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Convention
5
- module StructDefinition
6
- # A node wrapper for a Struct definition via inheritance.
7
- # @example
8
- # class MyStruct < Struct.new(:bar, :baz)
9
- # def foo
10
- # end
11
- # end
12
- class StructDefintionNode
13
- class << self
14
- # @example
15
- # s(:class,
16
- # s(:const, nil, :Foo),
17
- # s(:send,
18
- # s(:const, nil, :Struct), :new,
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
- struct_definition_node?(node.children[1])
34
- end
35
-
36
- private
37
-
38
- # @param struct_node [Parser::AST::Node]
39
- # @return [Boolean]
40
- def struct_definition_node?(struct_node)
41
- return false unless struct_node.is_a?(::Parser::AST::Node)
42
- return false unless struct_node&.type == :send
43
- return false unless struct_node.children[0]&.type == :const
44
- return false unless struct_node.children[0].children[1] == :Struct
45
- return false unless struct_node.children[1] == :new
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
- struct_attribute_nodes.map do |struct_def_param|
64
- next unless struct_def_param.type == :sym
65
- [struct_def_param, struct_def_param.children[0].to_s]
66
- end.compact
67
- end
68
-
69
- def keyword_init?
70
- keyword_init_param = struct_attribute_nodes.find do |struct_def_param|
71
- struct_def_param.type == :hash && struct_def_param.children[0].type == :pair &&
72
- struct_def_param.children[0].children[0].children[0] == :keyword_init
73
- end
74
-
75
- return false if keyword_init_param.nil?
76
-
77
- keyword_init_param.children[0].children[1].type == :true
78
- end
79
-
80
- # @return [Parser::AST::Node]
81
- def body_node
82
- node.children[2]
83
- end
84
-
85
- private
86
-
87
- # @return [Parser::AST::Node]
88
- attr_reader :node
89
-
90
- # @return [Parser::AST::Node]
91
- def struct_node
92
- node.children[1]
93
- end
94
-
95
- # @return [Array<Parser::AST::Node>]
96
- def struct_attribute_nodes
97
- struct_node.children[2..-1]
98
- end
99
- end
100
- end
101
- end
102
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ module StructDefinition
6
+ # A node wrapper for a Struct definition via inheritance.
7
+ # @example
8
+ # class MyStruct < Struct.new(:bar, :baz)
9
+ # def foo
10
+ # end
11
+ # end
12
+ class StructDefintionNode
13
+ class << self
14
+ # @example
15
+ # s(:class,
16
+ # s(:const, nil, :Foo),
17
+ # s(:send,
18
+ # s(:const, nil, :Struct), :new,
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
+ struct_definition_node?(node.children[1])
34
+ end
35
+
36
+ private
37
+
38
+ # @param struct_node [Parser::AST::Node]
39
+ # @return [Boolean]
40
+ def struct_definition_node?(struct_node)
41
+ return false unless struct_node.is_a?(::Parser::AST::Node)
42
+ return false unless struct_node&.type == :send
43
+ return false unless struct_node.children[0]&.type == :const
44
+ return false unless struct_node.children[0].children[1] == :Struct
45
+ return false unless struct_node.children[1] == :new
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
+ struct_attribute_nodes.map do |struct_def_param|
64
+ next unless struct_def_param.type == :sym
65
+ [struct_def_param, struct_def_param.children[0].to_s]
66
+ end.compact
67
+ end
68
+
69
+ def keyword_init?
70
+ keyword_init_param = struct_attribute_nodes.find do |struct_def_param|
71
+ struct_def_param.type == :hash && struct_def_param.children[0].type == :pair &&
72
+ struct_def_param.children[0].children[0].children[0] == :keyword_init
73
+ end
74
+
75
+ return false if keyword_init_param.nil?
76
+
77
+ keyword_init_param.children[0].children[1].type == :true
78
+ end
79
+
80
+ # @return [Parser::AST::Node]
81
+ def body_node
82
+ node.children[2]
83
+ end
84
+
85
+ private
86
+
87
+ # @return [Parser::AST::Node]
88
+ attr_reader :node
89
+
90
+ # @return [Parser::AST::Node]
91
+ def struct_node
92
+ node.children[1]
93
+ end
94
+
95
+ # @sg-ignore Need to add nil check here
96
+ # @return [Array<Parser::AST::Node>]
97
+ def struct_attribute_nodes
98
+ struct_node.children[2..-1]
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,164 +1,168 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Convention
5
- module StructDefinition
6
- autoload :StructDefintionNode, 'solargraph/convention/struct_definition/struct_definition_node'
7
- autoload :StructAssignmentNode, 'solargraph/convention/struct_definition/struct_assignment_node'
8
-
9
- module NodeProcessors
10
- class StructNode < Parser::NodeProcessor::Base
11
- # @return [Boolean] continue processing the next processor of the same node.
12
- def process
13
- return true if struct_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: struct_definition_node.class_name,
21
- docstring: docstring,
22
- visibility: :public,
23
- gates: region.closure.gates.freeze,
24
- source: :struct_definition
25
- )
26
- pins.push nspin
27
-
28
- # define initialize method
29
- initialize_method_pin = Pin::Method.new(
30
- name: 'initialize',
31
- parameters: [],
32
- scope: :instance,
33
- location: get_node_location(node),
34
- closure: nspin,
35
- visibility: :private,
36
- docstring: docstring,
37
- source: :struct_definition
38
- )
39
-
40
- pins.push initialize_method_pin
41
-
42
- struct_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: struct_definition_node.keyword_init? ? :kwarg : :arg,
47
- location: get_node_location(attribute_node),
48
- closure: initialize_method_pin,
49
- source: :struct_definition
50
- )
51
- )
52
- end
53
-
54
- # define attribute accessors and instance variables
55
- struct_definition_node.attributes.each do |attribute_node, attribute_name|
56
- [attribute_name, "#{attribute_name}="].each do |name|
57
- docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
58
-
59
- attribute_type = ComplexType.parse(tag_string(docs))
60
- return_type_comment = attribute_comment(docs, false)
61
- param_comment = attribute_comment(docs, true)
62
-
63
- method_pin = Pin::Method.new(
64
- name: name,
65
- parameters: [],
66
- scope: :instance,
67
- location: get_node_location(attribute_node),
68
- closure: nspin,
69
- docstring: YARD::Docstring.new(return_type_comment),
70
- # even assignments return the value
71
- comments: return_type_comment,
72
- return_type: attribute_type,
73
- visibility: :public,
74
- source: :struct_definition
75
- )
76
-
77
- if name.end_with?('=')
78
- method_pin.parameters << Pin::Parameter.new(
79
- name: attribute_name,
80
- location: get_node_location(attribute_node),
81
- closure: method_pin,
82
- return_type: attribute_type,
83
- comments: param_comment,
84
- source: :struct_definition
85
- )
86
-
87
- pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
88
- closure: method_pin,
89
- location: get_node_location(attribute_node),
90
- return_type: attribute_type,
91
- comments: "@type [#{attribute_type.rooted_tags}]",
92
- source: :struct_definition)
93
- end
94
-
95
- pins.push method_pin
96
- end
97
- end
98
-
99
- process_children region.update(closure: nspin, visibility: :public)
100
- false
101
- end
102
-
103
- private
104
-
105
- # @return [StructDefintionNode, StructAssignmentNode, nil]
106
- def struct_definition_node
107
- @struct_definition_node ||= if StructDefintionNode.match?(node)
108
- StructDefintionNode.new(node)
109
- elsif StructAssignmentNode.match?(node)
110
- StructAssignmentNode.new(node)
111
- end
112
- end
113
-
114
- # Gets/generates the relevant docstring for this struct & it's attributes
115
- # @return [YARD::Docstring]
116
- def docstring
117
- @docstring ||= parse_comments
118
- end
119
-
120
- # Parses any relevant comments for a struct int a yard docstring
121
- # @return [YARD::Docstring]
122
- def parse_comments
123
- struct_comments = comments_for(node) || ''
124
- struct_definition_node.attributes.each do |attr_node, attr_name|
125
- comment = comments_for(attr_node)
126
- next if comment.nil?
127
-
128
- # We should support specific comments for an attribute, and that can be either a @return on an @param
129
- # But since we merge into the struct_comments, then we should interpret either as a param
130
- comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
131
-
132
- struct_comments += "\n#{comment}"
133
- end
134
-
135
- Solargraph::Source.parse_docstring(struct_comments).to_docstring
136
- end
137
-
138
- # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
139
- #
140
- # @return [String]
141
- def tag_string(tag)
142
- tag&.types&.join(',') || 'undefined'
143
- end
144
-
145
- # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
146
- # @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
147
- #
148
- # @return [String] The formatted comment for the attribute
149
- def attribute_comment(tag, for_setter)
150
- return "" if tag.nil?
151
-
152
- suffix = "[#{tag_string(tag)}] #{tag.text}"
153
-
154
- if for_setter
155
- "@param #{tag.name} #{suffix}"
156
- else
157
- "@return #{suffix}"
158
- end
159
- end
160
- end
161
- end
162
- end
163
- end
164
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ module StructDefinition
6
+ autoload :StructDefintionNode, 'solargraph/convention/struct_definition/struct_definition_node'
7
+ autoload :StructAssignmentNode, 'solargraph/convention/struct_definition/struct_assignment_node'
8
+
9
+ module NodeProcessors
10
+ class StructNode < Parser::NodeProcessor::Base
11
+ # @return [Boolean] continue processing the next processor of the same node.
12
+ def process
13
+ return true if struct_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
+ # @sg-ignore flow sensitive typing needs to handle attrs
21
+ name: struct_definition_node.class_name,
22
+ docstring: docstring,
23
+ visibility: :public,
24
+ gates: region.closure.gates.freeze,
25
+ source: :struct_definition
26
+ )
27
+ pins.push nspin
28
+
29
+ # define initialize method
30
+ initialize_method_pin = Pin::Method.new(
31
+ name: 'initialize',
32
+ parameters: [],
33
+ scope: :instance,
34
+ location: get_node_location(node),
35
+ closure: nspin,
36
+ visibility: :private,
37
+ docstring: docstring,
38
+ source: :struct_definition
39
+ )
40
+
41
+ pins.push initialize_method_pin
42
+
43
+ # @sg-ignore flow sensitive typing needs to handle attrs
44
+ struct_definition_node.attributes.map do |attribute_node, attribute_name|
45
+ initialize_method_pin.parameters.push(
46
+ Pin::Parameter.new(
47
+ name: attribute_name,
48
+ decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
49
+ location: get_node_location(attribute_node),
50
+ closure: initialize_method_pin,
51
+ source: :struct_definition
52
+ )
53
+ )
54
+ end
55
+
56
+ # define attribute accessors and instance variables
57
+ # @sg-ignore flow sensitive typing needs to handle attrs
58
+ struct_definition_node.attributes.each do |attribute_node, attribute_name|
59
+ [attribute_name, "#{attribute_name}="].each do |name|
60
+ docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
61
+
62
+ attribute_type = ComplexType.parse(tag_string(docs))
63
+ return_type_comment = attribute_comment(docs, false)
64
+ param_comment = attribute_comment(docs, true)
65
+
66
+ method_pin = Pin::Method.new(
67
+ name: name,
68
+ parameters: [],
69
+ scope: :instance,
70
+ location: get_node_location(attribute_node),
71
+ closure: nspin,
72
+ docstring: YARD::Docstring.new(return_type_comment),
73
+ # even assignments return the value
74
+ comments: return_type_comment,
75
+ return_type: attribute_type,
76
+ visibility: :public,
77
+ source: :struct_definition
78
+ )
79
+
80
+ if name.end_with?('=')
81
+ method_pin.parameters << Pin::Parameter.new(
82
+ name: attribute_name,
83
+ location: get_node_location(attribute_node),
84
+ closure: method_pin,
85
+ return_type: attribute_type,
86
+ comments: param_comment,
87
+ source: :struct_definition
88
+ )
89
+
90
+ pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
91
+ closure: method_pin,
92
+ location: get_node_location(attribute_node),
93
+ return_type: attribute_type,
94
+ comments: "@type [#{attribute_type.rooted_tags}]",
95
+ source: :struct_definition)
96
+ end
97
+
98
+ pins.push method_pin
99
+ end
100
+ end
101
+
102
+ process_children region.update(closure: nspin, visibility: :public)
103
+ false
104
+ end
105
+
106
+ private
107
+
108
+ # @return [StructDefinition::StructDefintionNode, StructDefinition::StructAssignmentNode, nil]
109
+ def struct_definition_node
110
+ @struct_definition_node ||= if StructDefintionNode.match?(node)
111
+ StructDefintionNode.new(node)
112
+ elsif StructAssignmentNode.match?(node)
113
+ StructAssignmentNode.new(node)
114
+ end
115
+ end
116
+
117
+ # Gets/generates the relevant docstring for this struct & it's attributes
118
+ # @return [YARD::Docstring]
119
+ def docstring
120
+ @docstring ||= parse_comments
121
+ end
122
+
123
+ # Parses any relevant comments for a struct int a yard docstring
124
+ # @return [YARD::Docstring]
125
+ def parse_comments
126
+ struct_comments = comments_for(node) || ''
127
+ # @sg-ignore Need to add nil check here
128
+ struct_definition_node.attributes.each do |attr_node, attr_name|
129
+ comment = comments_for(attr_node)
130
+ next if comment.nil?
131
+
132
+ # We should support specific comments for an attribute, and that can be either a @return on an @param
133
+ # But since we merge into the struct_comments, then we should interpret either as a param
134
+ comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
135
+
136
+ struct_comments += "\n#{comment}"
137
+ end
138
+
139
+ Solargraph::Source.parse_docstring(struct_comments).to_docstring
140
+ end
141
+
142
+ # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
143
+ #
144
+ # @return [String]
145
+ def tag_string(tag)
146
+ tag&.types&.join(',') || 'undefined'
147
+ end
148
+
149
+ # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
150
+ # @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
151
+ #
152
+ # @return [String] The formatted comment for the attribute
153
+ def attribute_comment(tag, for_setter)
154
+ return "" if tag.nil?
155
+
156
+ suffix = "[#{tag_string(tag)}] #{tag.text}"
157
+
158
+ if for_setter
159
+ "@param #{tag.name} #{suffix}"
160
+ else
161
+ "@return #{suffix}"
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -1,53 +1,54 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Diagnostics
5
- # RequireNotFound reports required paths that could not be resolved to
6
- # either a file in the workspace or a gem.
7
- #
8
- class RequireNotFound < Base
9
- def diagnose source, api_map
10
- return [] unless source.parsed? && source.synchronized?
11
- result = []
12
- refs = {}
13
- map = api_map.source_map(source.filename)
14
- map.requires.each { |ref| refs[ref.name] = ref }
15
- api_map.missing_docs.each do |r|
16
- next unless refs.key?(r)
17
- result.push docs_error(r, refs[r].location)
18
- end
19
- api_map.unresolved_requires.each do |r|
20
- next unless refs.key?(r)
21
- result.push require_error(r, refs[r].location)
22
- end
23
- result
24
- end
25
-
26
- private
27
-
28
- # @param path [String]
29
- # @param location [Location]
30
- # @return [Hash]
31
- def docs_error path, location
32
- {
33
- range: location.range.to_hash,
34
- severity: Diagnostics::Severities::WARNING,
35
- source: 'RequireNotFound',
36
- message: "YARD docs not found for #{path}"
37
- }
38
- end
39
-
40
- # @param path [String]
41
- # @param location [Location]
42
- # @return [Hash]
43
- def require_error path, location
44
- {
45
- range: location.range.to_hash,
46
- severity: Diagnostics::Severities::WARNING,
47
- source: 'RequireNotFound',
48
- message: "Required path #{path} could not be resolved."
49
- }
50
- end
51
- end
52
- end
53
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Diagnostics
5
+ # RequireNotFound reports required paths that could not be resolved to
6
+ # either a file in the workspace or a gem.
7
+ #
8
+ class RequireNotFound < Base
9
+ def diagnose source, api_map
10
+ return [] unless source.parsed? && source.synchronized?
11
+ result = []
12
+ refs = {}
13
+ # @sg-ignore Need to add nil check here
14
+ map = api_map.source_map(source.filename)
15
+ map.requires.each { |ref| refs[ref.name] = ref }
16
+ api_map.missing_docs.each do |r|
17
+ next unless refs.key?(r)
18
+ result.push docs_error(r, refs[r].location)
19
+ end
20
+ api_map.unresolved_requires.each do |r|
21
+ next unless refs.key?(r)
22
+ result.push require_error(r, refs[r].location)
23
+ end
24
+ result
25
+ end
26
+
27
+ private
28
+
29
+ # @param path [String]
30
+ # @param location [Location]
31
+ # @return [Hash]
32
+ def docs_error path, location
33
+ {
34
+ range: location.range.to_hash,
35
+ severity: Diagnostics::Severities::WARNING,
36
+ source: 'RequireNotFound',
37
+ message: "YARD docs not found for #{path}"
38
+ }
39
+ end
40
+
41
+ # @param path [String]
42
+ # @param location [Location]
43
+ # @return [Hash]
44
+ def require_error path, location
45
+ {
46
+ range: location.range.to_hash,
47
+ severity: Diagnostics::Severities::WARNING,
48
+ source: 'RequireNotFound',
49
+ message: "Required path #{path} could not be resolved."
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end