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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +24 -2
  3. data/.github/workflows/plugins.yml +19 -1
  4. data/.github/workflows/rspec.yml +17 -2
  5. data/.github/workflows/typecheck.yml +6 -0
  6. data/CHANGELOG.md +54 -0
  7. data/Gemfile +0 -3
  8. data/lib/solargraph/api_map/index.rb +28 -4
  9. data/lib/solargraph/api_map/store.rb +19 -0
  10. data/lib/solargraph/api_map.rb +91 -80
  11. data/lib/solargraph/cache_dir.rb +58 -0
  12. data/lib/solargraph/collection/base.rb +50 -0
  13. data/lib/solargraph/collection/core.rb +17 -0
  14. data/lib/solargraph/collection/gem.rb +59 -0
  15. data/lib/solargraph/collection/stdlib.rb +25 -0
  16. data/lib/solargraph/collection.rb +30 -0
  17. data/lib/solargraph/complex_type/unique_type.rb +13 -0
  18. data/lib/solargraph/complex_type.rb +23 -3
  19. data/lib/solargraph/convention.rb +5 -7
  20. data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
  21. data/lib/solargraph/diagnostics/type_check.rb +0 -1
  22. data/lib/solargraph/external.rb +187 -0
  23. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  24. data/lib/solargraph/language_server/host/dispatch.rb +4 -2
  25. data/lib/solargraph/language_server/host.rb +10 -2
  26. data/lib/solargraph/language_server/message/completion_item/resolve.rb +10 -3
  27. data/lib/solargraph/language_server/message/text_document/definition.rb +5 -2
  28. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
  29. data/lib/solargraph/library.rb +26 -53
  30. data/lib/solargraph/metagem.rb +80 -0
  31. data/lib/solargraph/parser/node_processor/base.rb +6 -0
  32. data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
  33. data/lib/solargraph/parser/parser_gem/node_methods.rb +29 -6
  34. data/lib/solargraph/parser/parser_gem/node_processors/class_definition/class_assignment_node.rb +98 -0
  35. data/lib/solargraph/parser/parser_gem/node_processors/class_definition.rb +54 -0
  36. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +1 -0
  37. data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_assignment_node.rb +65 -0
  38. data/lib/solargraph/parser/parser_gem/node_processors/data_definition/data_definition_node.rb +97 -0
  39. data/lib/solargraph/parser/parser_gem/node_processors/data_definition.rb +110 -0
  40. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +1 -0
  41. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +2 -0
  42. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  43. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +185 -0
  44. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node.rb +66 -0
  45. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node.rb +108 -0
  46. data/lib/solargraph/parser/parser_gem/node_processors/struct_definition.rb +170 -0
  47. data/lib/solargraph/parser/parser_gem/node_processors.rb +33 -29
  48. data/lib/solargraph/pin/base.rb +25 -1
  49. data/lib/solargraph/pin/base_variable.rb +31 -1
  50. data/lib/solargraph/pin/callable.rb +11 -2
  51. data/lib/solargraph/pin/closure.rb +17 -0
  52. data/lib/solargraph/pin/delegated_method.rb +5 -0
  53. data/lib/solargraph/pin/duck_method.rb +36 -16
  54. data/lib/solargraph/pin/factory_parameter.rb +84 -0
  55. data/lib/solargraph/pin/instance_variable.rb +45 -0
  56. data/lib/solargraph/pin/method.rb +10 -0
  57. data/lib/solargraph/pin/method_alias.rb +4 -0
  58. data/lib/solargraph/pin/parameter.rb +1 -1
  59. data/lib/solargraph/pin/reference/included_mixin.rb +22 -0
  60. data/lib/solargraph/pin/reference.rb +1 -0
  61. data/lib/solargraph/pin.rb +1 -0
  62. data/lib/solargraph/plugin/active_support.rb +100 -0
  63. data/lib/solargraph/plugin/addon.rb +16 -0
  64. data/lib/solargraph/plugin/base.rb +25 -0
  65. data/lib/solargraph/plugin/panel.rb +37 -0
  66. data/lib/solargraph/plugin.rb +26 -0
  67. data/lib/solargraph/rbs_collection.rb +119 -0
  68. data/lib/solargraph/rbs_map/base.rb +31 -0
  69. data/lib/solargraph/rbs_map/conversions.rb +109 -48
  70. data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
  71. data/lib/solargraph/rbs_map/core_fills.rb +1 -1
  72. data/lib/solargraph/rbs_map/gem.rb +16 -0
  73. data/lib/solargraph/rbs_map/helpers.rb +61 -0
  74. data/lib/solargraph/rbs_map/path.rb +19 -0
  75. data/lib/solargraph/rbs_map/stdlib.rb +24 -0
  76. data/lib/solargraph/rbs_map.rb +7 -198
  77. data/lib/solargraph/rbs_translator.rb +105 -70
  78. data/lib/solargraph/repo.rb +177 -0
  79. data/lib/solargraph/shell.rb +49 -99
  80. data/lib/solargraph/source/chain/call.rb +58 -14
  81. data/lib/solargraph/source/chain/literal.rb +17 -17
  82. data/lib/solargraph/source/chain/parameter.rb +79 -0
  83. data/lib/solargraph/source/chain.rb +8 -0
  84. data/lib/solargraph/source/node_map.rb +27 -0
  85. data/lib/solargraph/source/source_chainer.rb +40 -44
  86. data/lib/solargraph/source.rb +17 -0
  87. data/lib/solargraph/source_map/call.rb +18 -0
  88. data/lib/solargraph/source_map/clip.rb +5 -3
  89. data/lib/solargraph/source_map/mapper.rb +6 -2
  90. data/lib/solargraph/source_map.rb +28 -9
  91. data/lib/solargraph/type_checker/rules.rb +3 -2
  92. data/lib/solargraph/type_checker.rb +4 -1
  93. data/lib/solargraph/version.rb +1 -1
  94. data/lib/solargraph/workspace.rb +0 -1
  95. data/lib/solargraph/yard_map/cache.rb +1 -1
  96. data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
  97. data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
  98. data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
  99. data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
  100. data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
  101. data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
  102. data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
  103. data/lib/solargraph/yard_map/directives.rb +5 -2
  104. data/lib/solargraph/yard_map/helpers.rb +1 -1
  105. data/lib/solargraph/yard_map/macro.rb +85 -6
  106. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
  107. data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
  108. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
  109. data/lib/solargraph/yard_map/mapper.rb +2 -2
  110. data/lib/solargraph/yard_map.rb +1 -1
  111. data/lib/solargraph/yardoc.rb +43 -60
  112. data/lib/solargraph.rb +8 -3
  113. data/rbs/fills/boolean/0/boolean.rbs +12 -0
  114. data/solargraph.gemspec +2 -2
  115. metadata +41 -18
  116. data/lib/solargraph/convention/active_support_concern.rb +0 -111
  117. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +0 -61
  118. data/lib/solargraph/convention/data_definition/data_definition_node.rb +0 -93
  119. data/lib/solargraph/convention/data_definition.rb +0 -108
  120. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +0 -62
  121. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +0 -103
  122. data/lib/solargraph/convention/struct_definition.rb +0 -168
  123. data/lib/solargraph/doc_map.rb +0 -439
  124. data/lib/solargraph/gem_pins.rb +0 -87
  125. data/lib/solargraph/pin_cache.rb +0 -248
  126. data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
  127. data/lib/solargraph/workspace/gemspecs.rb +0 -373
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Parser
5
+ module ParserGem
6
+ module NodeProcessors
7
+ module StructDefinition
8
+ autoload :StructDefintionNode, 'solargraph/parser/parser_gem/node_processors/struct_definition/struct_definition_node'
9
+ autoload :StructAssignmentNode, 'solargraph/parser/parser_gem/node_processors/struct_definition/struct_assignment_node'
10
+
11
+ class StructNode < Parser::NodeProcessor::Base
12
+ # @return [Boolean] continue processing the next processor of the same node.
13
+ def process
14
+ return true if struct_definition_node.nil?
15
+
16
+ loc = get_node_location(node)
17
+ nspin = Solargraph::Pin::Namespace.new(
18
+ type: :class,
19
+ location: loc,
20
+ closure: region.closure,
21
+ # @sg-ignore flow sensitive typing needs to handle attrs
22
+ name: struct_definition_node.class_name,
23
+ docstring: docstring,
24
+ visibility: :public,
25
+ gates: region.closure.gates.freeze,
26
+ source: :struct_definition
27
+ )
28
+ pins.push nspin
29
+
30
+ # define initialize method
31
+ initialize_method_pin = Pin::Method.new(
32
+ name: 'initialize',
33
+ parameters: [],
34
+ scope: :instance,
35
+ location: get_node_location(node),
36
+ closure: nspin,
37
+ visibility: :private,
38
+ docstring: docstring,
39
+ source: :struct_definition
40
+ )
41
+
42
+ pins.push initialize_method_pin
43
+
44
+ # @sg-ignore flow sensitive typing needs to handle attrs
45
+ struct_definition_node.attributes.map do |attribute_node, attribute_name|
46
+ initialize_method_pin.parameters.push(
47
+ Pin::Parameter.new(
48
+ name: attribute_name,
49
+ decl: struct_definition_node.keyword_init? ? :kwoptarg : :arg,
50
+ location: get_node_location(attribute_node),
51
+ closure: initialize_method_pin,
52
+ source: :struct_definition
53
+ )
54
+ )
55
+ end
56
+
57
+ # define attribute accessors and instance variables
58
+ # @sg-ignore flow sensitive typing needs to handle attrs
59
+ struct_definition_node.attributes.each do |attribute_node, attribute_name|
60
+ [attribute_name, "#{attribute_name}="].each do |name|
61
+ docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
62
+
63
+ attribute_type = ComplexType.parse(tag_string(docs))
64
+ return_type_comment = attribute_comment(docs, false)
65
+ param_comment = attribute_comment(docs, true)
66
+
67
+ method_pin = Pin::Method.new(
68
+ name: name,
69
+ parameters: [],
70
+ scope: :instance,
71
+ location: get_node_location(attribute_node),
72
+ closure: nspin,
73
+ docstring: YARD::Docstring.new(return_type_comment),
74
+ # even assignments return the value
75
+ comments: return_type_comment,
76
+ return_type: attribute_type,
77
+ visibility: :public,
78
+ source: :struct_definition
79
+ )
80
+
81
+ if name.end_with?('=')
82
+ method_pin.parameters << Pin::Parameter.new(
83
+ name: attribute_name,
84
+ location: get_node_location(attribute_node),
85
+ closure: method_pin,
86
+ return_type: attribute_type,
87
+ comments: param_comment,
88
+ source: :struct_definition
89
+ )
90
+
91
+ pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
92
+ closure: method_pin,
93
+ location: get_node_location(attribute_node),
94
+ return_type: attribute_type,
95
+ comments: "@type [#{attribute_type.rooted_tags}]",
96
+ source: :struct_definition)
97
+ end
98
+
99
+ pins.push method_pin
100
+ end
101
+ end
102
+
103
+ process_children region.update(closure: nspin, visibility: :public)
104
+ false
105
+ end
106
+
107
+ private
108
+
109
+ # @return [StructDefinition::StructDefintionNode, StructDefinition::StructAssignmentNode, nil]
110
+ def struct_definition_node
111
+ @struct_definition_node ||= if StructDefintionNode.match?(node)
112
+ StructDefintionNode.new(node)
113
+ elsif StructAssignmentNode.match?(node)
114
+ StructAssignmentNode.new(node)
115
+ end
116
+ end
117
+
118
+ # Gets/generates the relevant docstring for this struct & it's attributes
119
+ # @return [YARD::Docstring]
120
+ def docstring
121
+ @docstring ||= parse_comments
122
+ end
123
+
124
+ # Parses any relevant comments for a struct int a yard docstring
125
+ # @return [YARD::Docstring]
126
+ def parse_comments
127
+ struct_comments = comments_for(node) || ''
128
+ # @sg-ignore Need to add nil check here
129
+ struct_definition_node.attributes.each do |attr_node, attr_name|
130
+ comment = comments_for(attr_node)
131
+ next if comment.nil?
132
+
133
+ # We should support specific comments for an attribute, and that can be either a @return on an @param
134
+ # But since we merge into the struct_comments, then we should interpret either as a param
135
+ comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
136
+
137
+ struct_comments += "\n#{comment}"
138
+ end
139
+
140
+ Solargraph::Source.parse_docstring(struct_comments).to_docstring
141
+ end
142
+
143
+ # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute.xtract_
144
+ #
145
+ # @return [String]
146
+ def tag_string tag
147
+ tag&.types&.join(',') || 'undefined'
148
+ end
149
+
150
+ # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
151
+ # @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag
152
+ #
153
+ # @return [String] The formatted comment for the attribute
154
+ def attribute_comment tag, for_setter
155
+ return '' if tag.nil?
156
+
157
+ suffix = "[#{tag_string(tag)}] #{tag.text}"
158
+
159
+ if for_setter
160
+ "@param #{tag.name} #{suffix}"
161
+ else
162
+ "@return #{suffix}"
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -6,31 +6,34 @@ module Solargraph
6
6
  module Parser
7
7
  module ParserGem
8
8
  module NodeProcessors
9
- autoload :BeginNode, 'solargraph/parser/parser_gem/node_processors/begin_node'
10
- autoload :DefNode, 'solargraph/parser/parser_gem/node_processors/def_node'
11
- autoload :DefsNode, 'solargraph/parser/parser_gem/node_processors/defs_node'
12
- autoload :SendNode, 'solargraph/parser/parser_gem/node_processors/send_node'
13
- autoload :NamespaceNode, 'solargraph/parser/parser_gem/node_processors/namespace_node'
14
- autoload :SclassNode, 'solargraph/parser/parser_gem/node_processors/sclass_node'
15
- autoload :IvasgnNode, 'solargraph/parser/parser_gem/node_processors/ivasgn_node'
16
- autoload :IfNode, 'solargraph/parser/parser_gem/node_processors/if_node'
17
- autoload :CvasgnNode, 'solargraph/parser/parser_gem/node_processors/cvasgn_node'
18
- autoload :LvasgnNode, 'solargraph/parser/parser_gem/node_processors/lvasgn_node'
19
- autoload :GvasgnNode, 'solargraph/parser/parser_gem/node_processors/gvasgn_node'
20
- autoload :CasgnNode, 'solargraph/parser/parser_gem/node_processors/casgn_node'
21
- autoload :MasgnNode, 'solargraph/parser/parser_gem/node_processors/masgn_node'
22
- autoload :AliasNode, 'solargraph/parser/parser_gem/node_processors/alias_node'
23
- autoload :ArgsNode, 'solargraph/parser/parser_gem/node_processors/args_node'
24
- autoload :BlockNode, 'solargraph/parser/parser_gem/node_processors/block_node'
25
- autoload :OrasgnNode, 'solargraph/parser/parser_gem/node_processors/orasgn_node'
26
- autoload :OpasgnNode, 'solargraph/parser/parser_gem/node_processors/opasgn_node'
27
- autoload :SymNode, 'solargraph/parser/parser_gem/node_processors/sym_node'
28
- autoload :ResbodyNode, 'solargraph/parser/parser_gem/node_processors/resbody_node'
29
- autoload :UntilNode, 'solargraph/parser/parser_gem/node_processors/until_node'
30
- autoload :WhenNode, 'solargraph/parser/parser_gem/node_processors/when_node'
31
- autoload :WhileNode, 'solargraph/parser/parser_gem/node_processors/while_node'
32
- autoload :AndNode, 'solargraph/parser/parser_gem/node_processors/and_node'
33
- autoload :OrNode, 'solargraph/parser/parser_gem/node_processors/or_node'
9
+ autoload :BeginNode, 'solargraph/parser/parser_gem/node_processors/begin_node'
10
+ autoload :DefNode, 'solargraph/parser/parser_gem/node_processors/def_node'
11
+ autoload :DefsNode, 'solargraph/parser/parser_gem/node_processors/defs_node'
12
+ autoload :SendNode, 'solargraph/parser/parser_gem/node_processors/send_node'
13
+ autoload :NamespaceNode, 'solargraph/parser/parser_gem/node_processors/namespace_node'
14
+ autoload :SclassNode, 'solargraph/parser/parser_gem/node_processors/sclass_node'
15
+ autoload :IvasgnNode, 'solargraph/parser/parser_gem/node_processors/ivasgn_node'
16
+ autoload :IfNode, 'solargraph/parser/parser_gem/node_processors/if_node'
17
+ autoload :CvasgnNode, 'solargraph/parser/parser_gem/node_processors/cvasgn_node'
18
+ autoload :LvasgnNode, 'solargraph/parser/parser_gem/node_processors/lvasgn_node'
19
+ autoload :GvasgnNode, 'solargraph/parser/parser_gem/node_processors/gvasgn_node'
20
+ autoload :CasgnNode, 'solargraph/parser/parser_gem/node_processors/casgn_node'
21
+ autoload :MasgnNode, 'solargraph/parser/parser_gem/node_processors/masgn_node'
22
+ autoload :AliasNode, 'solargraph/parser/parser_gem/node_processors/alias_node'
23
+ autoload :ArgsNode, 'solargraph/parser/parser_gem/node_processors/args_node'
24
+ autoload :BlockNode, 'solargraph/parser/parser_gem/node_processors/block_node'
25
+ autoload :OrasgnNode, 'solargraph/parser/parser_gem/node_processors/orasgn_node'
26
+ autoload :OpasgnNode, 'solargraph/parser/parser_gem/node_processors/opasgn_node'
27
+ autoload :SymNode, 'solargraph/parser/parser_gem/node_processors/sym_node'
28
+ autoload :ResbodyNode, 'solargraph/parser/parser_gem/node_processors/resbody_node'
29
+ autoload :UntilNode, 'solargraph/parser/parser_gem/node_processors/until_node'
30
+ autoload :WhenNode, 'solargraph/parser/parser_gem/node_processors/when_node'
31
+ autoload :WhileNode, 'solargraph/parser/parser_gem/node_processors/while_node'
32
+ autoload :AndNode, 'solargraph/parser/parser_gem/node_processors/and_node'
33
+ autoload :OrNode, 'solargraph/parser/parser_gem/node_processors/or_node'
34
+ autoload :ClassDefinition, 'solargraph/parser/parser_gem/node_processors/class_definition'
35
+ autoload :StructDefinition, 'solargraph/parser/parser_gem/node_processors/struct_definition'
36
+ autoload :DataDefinition, 'solargraph/parser/parser_gem/node_processors/data_definition'
34
37
  end
35
38
  end
36
39
 
@@ -44,8 +47,8 @@ module Solargraph
44
47
  register :defs, ParserGem::NodeProcessors::DefsNode
45
48
  register :if, ParserGem::NodeProcessors::IfNode
46
49
  register :send, ParserGem::NodeProcessors::SendNode
47
- register :class, Convention::StructDefinition::NodeProcessors::StructNode
48
- register :class, Convention::DataDefinition::NodeProcessors::DataNode
50
+ register :class, ParserGem::NodeProcessors::StructDefinition::StructNode
51
+ register :class, ParserGem::NodeProcessors::DataDefinition::DataNode
49
52
  register :class, ParserGem::NodeProcessors::NamespaceNode
50
53
  register :module, ParserGem::NodeProcessors::NamespaceNode
51
54
  register :sclass, ParserGem::NodeProcessors::SclassNode
@@ -53,8 +56,9 @@ module Solargraph
53
56
  register :cvasgn, ParserGem::NodeProcessors::CvasgnNode
54
57
  register :lvasgn, ParserGem::NodeProcessors::LvasgnNode
55
58
  register :gvasgn, ParserGem::NodeProcessors::GvasgnNode
56
- register :casgn, Convention::StructDefinition::NodeProcessors::StructNode
57
- register :casgn, Convention::DataDefinition::NodeProcessors::DataNode
59
+ register :casgn, ParserGem::NodeProcessors::StructDefinition::StructNode
60
+ register :casgn, ParserGem::NodeProcessors::DataDefinition::DataNode
61
+ register :casgn, ParserGem::NodeProcessors::ClassDefinition::ClassNode
58
62
  register :casgn, ParserGem::NodeProcessors::CasgnNode
59
63
  register :masgn, ParserGem::NodeProcessors::MasgnNode
60
64
  register :alias, ParserGem::NodeProcessors::AliasNode
@@ -158,7 +158,17 @@ module Solargraph
158
158
  # @param other [self]
159
159
  # @return [Pin::Closure, nil]
160
160
  def combine_closure other
161
- choose_pin_attr_with_same_name(other, :closure)
161
+ chosen = choose_pin_attr_with_same_name(other, :closure)
162
+ return chosen unless chosen.is_a?(Pin::Namespace) && chosen.generics.empty?
163
+
164
+ # Combined types may name type parameters only the other closure declares
165
+ own = closure
166
+ return own if own.is_a?(Pin::Namespace) && !own.generics.empty?
167
+
168
+ theirs = other.closure
169
+ return theirs if theirs.is_a?(Pin::Namespace) && !theirs.generics.empty?
170
+
171
+ chosen
162
172
  end
163
173
 
164
174
  # @param other [self]
@@ -435,6 +445,7 @@ module Solargraph
435
445
  # @param context_type [ComplexType] The receiver type
436
446
  # @return [self]
437
447
  def resolve_generics definitions, context_type
448
+ definitions = declaring_definitions(definitions)
438
449
  transform_types { |t| t&.resolve_generics(definitions, context_type) }
439
450
  end
440
451
 
@@ -731,6 +742,19 @@ module Solargraph
731
742
 
732
743
  private
733
744
 
745
+ # Declarations of a reopened generic may spell its parameters
746
+ # differently, so bind by position against this pin's own one.
747
+ #
748
+ # @param definitions [Pin::Namespace, nil]
749
+ # @return [Pin::Namespace, nil]
750
+ def declaring_definitions definitions
751
+ own = closure
752
+ return definitions unless definitions.is_a?(Pin::Namespace) && own.is_a?(Pin::Namespace)
753
+ return definitions unless own.path == definitions.path && !own.generics.empty?
754
+
755
+ own
756
+ end
757
+
734
758
  # @return [void]
735
759
  def parse_comments
736
760
  # HACK: Avoid a NoMethodError on nil with empty overload tags
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rbs'
4
+
3
5
  module Solargraph
4
6
  module Pin
5
7
  class BaseVariable < Base
@@ -14,6 +16,9 @@ module Solargraph
14
16
  # @return [Range, nil]
15
17
  attr_reader :presence
16
18
 
19
+ # @return [String, nil]
20
+ attr_reader :type_assertion
21
+
17
22
  # @param return_type [ComplexType, nil]
18
23
  # @param assignment [Parser::AST::Node, nil] First assignment
19
24
  # that was made to this variable
@@ -45,12 +50,16 @@ module Solargraph
45
50
  # @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
46
51
  # @see https://en.wikipedia.org/wiki/Intersection_type#TypeScript_example
47
52
  # @param presence [Range, nil]
53
+ # @param type_assertion [String, nil] RBS type from a trailing
54
+ # rbs-inline `#: TYPE` comment on the assignment
48
55
  # @param [Hash{Symbol => Object}] splat
49
56
  def initialize assignment: nil, assignments: [], mass_assignment: nil,
50
57
  presence: nil, return_type: nil,
51
58
  intersection_return_type: nil, exclude_return_type: nil,
59
+ type_assertion: nil,
52
60
  **splat
53
61
  super(**splat)
62
+ @type_assertion = type_assertion
54
63
  @assignments = (assignment.nil? ? [] : [assignment]) + assignments
55
64
  # @type [nil, ::Array(Parser::AST::Node, Integer)]
56
65
  @mass_assignment = mass_assignment
@@ -95,7 +104,8 @@ module Solargraph
95
104
  return_type: combine_return_type(other),
96
105
  intersection_return_type: combine_types(other, :intersection_return_type),
97
106
  exclude_return_type: combine_types(other, :exclude_return_type),
98
- presence: combine_presence(other)
107
+ presence: combine_presence(other),
108
+ type_assertion: choose(other, :type_assertion)
99
109
  })
100
110
  super(other, new_attrs)
101
111
  end
@@ -170,6 +180,9 @@ module Solargraph
170
180
  end
171
181
  end
172
182
  types
183
+ rescue FileNotFoundError
184
+ # @todo Necessary for pins from source maps that are not part of the workspace
185
+ [ComplexType::UNDEFINED]
173
186
  end
174
187
 
175
188
  # @param api_map [ApiMap]
@@ -364,12 +377,29 @@ module Solargraph
364
377
  :instance
365
378
  end
366
379
 
380
+ # An rbs-inline type assertion takes precedence over a @type tag,
381
+ # as inline RBS method signatures do over YARD tags.
382
+ #
367
383
  # @return [ComplexType, nil]
368
384
  def generate_complex_type
385
+ asserted = type_from_assertion
386
+ return asserted unless asserted.nil?
369
387
  tag = docstring.tag(:type)
370
388
  return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
371
389
  nil
372
390
  end
391
+
392
+ # @return [ComplexType, nil]
393
+ def type_from_assertion
394
+ assertion = type_assertion
395
+ return nil if assertion.nil? || assertion.empty?
396
+ @type_from_assertion ||= begin
397
+ rbs_type = RBS::Parser.parse_type(assertion, require_eof: true)
398
+ RbsTranslator.to_complex_type(rbs_type) unless rbs_type.nil?
399
+ rescue RBS::ParsingError
400
+ nil
401
+ end
402
+ end
373
403
  end
374
404
  end
375
405
  end
@@ -14,12 +14,15 @@ module Solargraph
14
14
  # @param block [Signature, nil]
15
15
  # @param return_type [ComplexType, nil]
16
16
  # @param parameters [::Array<Pin::Parameter>]
17
+ # @param block_required [Boolean] Whether callers must pass a block, per
18
+ # an RBS non-optional block (`{ ... }` rather than `?{ ... }`).
17
19
  # @param [Hash{Symbol => Object}] splat
18
- def initialize block: nil, return_type: nil, parameters: [], **splat
20
+ def initialize block: nil, return_type: nil, parameters: [], block_required: false, **splat
19
21
  super(**splat)
20
22
  @block = block
21
23
  @return_type = return_type
22
24
  @parameters = parameters
25
+ @block_required = block_required
23
26
  end
24
27
 
25
28
  def reset_generated!
@@ -55,6 +58,7 @@ module Solargraph
55
58
  def combine_with other, attrs = {}
56
59
  new_attrs = {
57
60
  block: combine_blocks(other),
61
+ block_required: block_required? || other.block_required?,
58
62
  return_type: combine_return_type(other)
59
63
  }.merge(attrs)
60
64
  new_attrs[:parameters] = choose_parameters(other).clone.freeze unless new_attrs.key?(:parameters)
@@ -241,7 +245,7 @@ module Solargraph
241
245
  argcount = arguments.length
242
246
  parcount = mandatory_positional_param_count
243
247
  parcount -= 1 if !parameters.empty? && parameters.last.block?
244
- return false if block? && !with_block
248
+ return false if block? && block_required? && !with_block
245
249
  # @todo this and its caller should be changed so that this can
246
250
  # look at the kwargs provided and check names against what
247
251
  # we acccept
@@ -267,6 +271,11 @@ module Solargraph
267
271
  !!@block
268
272
  end
269
273
 
274
+ # @return [Boolean]
275
+ def block_required?
276
+ !!@block_required
277
+ end
278
+
270
279
  protected
271
280
 
272
281
  attr_writer :block
@@ -6,6 +6,23 @@ module Solargraph
6
6
  # @return [::Symbol] :class or :instance
7
7
  attr_reader :scope
8
8
 
9
+ # Override the pin's scope.
10
+ #
11
+ # Scope is normally determined by the syntax that declared the pin, but
12
+ # YARD's `@!scope` directive can change it after the fact. Any values
13
+ # derived from the scope, such as the pin's path and context, are
14
+ # recalculated.
15
+ #
16
+ # @param scope [::Symbol] :class or :instance
17
+ # @return [void]
18
+ def scope= scope
19
+ return if @scope == scope
20
+
21
+ @scope = scope
22
+ # remove cached values generated from scope
23
+ reset_generated!
24
+ end
25
+
9
26
  # @param scope [::Symbol] :class or :instance
10
27
  # @param generics [::Array<Pin::String>, nil]
11
28
  # @param generic_defaults [Hash{String => ComplexType}]
@@ -5,6 +5,11 @@ module Solargraph
5
5
  # A DelegatedMethod is a more complicated version of a MethodAlias that
6
6
  # allows aliasing a method from a different closure (class/module etc).
7
7
  class DelegatedMethod < Pin::Method
8
+ # @return [Boolean]
9
+ def body?
10
+ false
11
+ end
12
+
8
13
  # A DelegatedMethod can be constructed with either a :resolved_method
9
14
  # pin, or a :receiver_chain. When a :receiver_chain is supplied, it
10
15
  # will be used to *dynamically* resolve a receiver type within the
@@ -1,16 +1,36 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- # DuckMethod pins are used to add completion items for type tags that
6
- # use duck typing, e.g., `@param file [#read]`.
7
- #
8
- class DuckMethod < Pin::Method
9
- # @param location [Solargraph::Location]
10
- # @param name [String]
11
- # def initialize location, name
12
- # # super(location, '', name, nil, :instance, :public, [])
13
- # end
14
- end
15
- end
16
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # DuckMethod pins are used to add completion items for type tags that
6
+ # use duck typing, e.g., `@param file [#read]`.
7
+ #
8
+ class DuckMethod < Pin::Method
9
+ # A duck-type tag has no syntax for arguments, so the default empty
10
+ # #parameters would synthesize a zero-arg signature no real call matches.
11
+ #
12
+ # @param splat [Hash{Symbol => Object}]
13
+ def initialize **splat
14
+ super(parameters: accepts_any_arguments, **splat)
15
+ end
16
+
17
+ # @return [::Array<Pin::Parameter>]
18
+ def accepts_any_arguments
19
+ [
20
+ Pin::Parameter.new(decl: :restarg, name: 'args', closure: self, source: :api_map),
21
+ Pin::Parameter.new(decl: :kwrestarg, name: 'kwargs', closure: self, source: :api_map)
22
+ ]
23
+ end
24
+
25
+ # A synthetic pin sits in no ancestor chain and has no closure. Letting
26
+ # the inherited walk find a type sends #typify on to `closure.gates`,
27
+ # which raises.
28
+ #
29
+ # @param _api_map [ApiMap]
30
+ # @return [Array<Pin::Method>]
31
+ def rest_of_stack _api_map
32
+ []
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # A method parameter with a literal value used in a factory method.
6
+ #
7
+ # @example
8
+ # RSpec.shared_examples 'some examples'
9
+ #
10
+ # FactoryParameter.new(
11
+ # method_name: 'shared_examples',
12
+ # method_namespace: 'RSpec',
13
+ # method_scope: :class,
14
+ # param_name: 'name',
15
+ # value: 'some examples',
16
+ # decl: :arg,
17
+ # return_type: 'void'
18
+ # )
19
+ class FactoryParameter < Base
20
+ # @return [String]
21
+ attr_reader :method_name
22
+ # @return [String]
23
+ attr_reader :method_namespace
24
+ # @return [Symbol] :class or :instance
25
+ attr_reader :method_scope
26
+ # @return [String, nil]
27
+ attr_reader :param_name
28
+ # @return [::String, ::Symbol] The literal value
29
+ attr_reader :value
30
+ # @return [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
31
+ attr_reader :decl
32
+ # @return [Location, nil]
33
+ attr_reader :location
34
+
35
+ # @param method_name [String] The name of the method that this parameter belongs to
36
+ # @param method_namespace [String] The class of the method that this parameter belongs to
37
+ # @param method_scope [Symbol] The scope of the method, either :class or :instance
38
+ # @param param_name [String, nil] The name of the parameter
39
+ # @param value [String, Symbol] The value of the parameter
40
+ # @param decl [::Symbol] :arg, :kwarg
41
+ # @param location [Location, nil] The location of the parameter in the source code
42
+ # @param return_type [String, nil] The return type of the method that this parameter belongs to
43
+ def initialize method_name:,
44
+ method_namespace:,
45
+ method_scope:,
46
+ param_name:,
47
+ value:,
48
+ return_type:,
49
+ decl: :arg,
50
+ location: nil
51
+ super(location: location)
52
+ @method_name = method_name
53
+ @method_namespace = method_namespace
54
+ @method_scope = method_scope
55
+ @param_name = param_name
56
+ @value = value
57
+ @decl = decl
58
+ @return_type = return_type
59
+ end
60
+
61
+ def name
62
+ param_name
63
+ end
64
+
65
+ def text_documentation
66
+ "#{method_path}(#{param_name}) = #{value.inspect}"
67
+ end
68
+
69
+ # @return [String]
70
+ def method_path
71
+ # @sg-ignore false failure on method_scope "Wrong argument type for Solargraph::Pin::Base#==: other expected
72
+ # Solargraph::Pin::Base, received :instance"
73
+ @method_path ||= "#{method_namespace}#{method_scope == :instance ? '#' : '.'}#{method_name}"
74
+ end
75
+
76
+ private
77
+
78
+ def inner_desc
79
+ "method_path=#{method_path}, value=#{value.inspect}, decl=#{decl.inspect}, " \
80
+ "return_type=#{return_type&.to_s || 'nil'}"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -33,6 +33,51 @@ module Solargraph
33
33
  def nearly? other
34
34
  super && binder == other.binder
35
35
  end
36
+
37
+ # Same-file requirement only applies when +presence+ is set; an
38
+ # unnarrowed ivar has none and can be assigned and read in
39
+ # different files (e.g. ancestor class's method vs. descendant's).
40
+ #
41
+ # @param other_closure [Pin::Closure]
42
+ # @param other_loc [Location]
43
+ def visible_at? other_closure, other_loc
44
+ return false if presence && location&.filename != other_loc.filename
45
+ # @sg-ignore flow sensitive typing needs to handle attrs
46
+ return false if presence && !presence.include?(other_loc.range.start)
47
+
48
+ visible_in_closure?(other_closure)
49
+ end
50
+
51
+ private
52
+
53
+ # Unlike BaseVariable, doesn't stop at a lexically-mismatched
54
+ # Namespace pin: #get_instance_variable_pins already restricts
55
+ # candidates to the reading namespace and its ancestors, so
56
+ # reaching one here means visible via inheritance.
57
+ #
58
+ # @param viewing_closure [Pin::Closure]
59
+ # @return [Boolean]
60
+ def visible_in_closure? viewing_closure
61
+ return false if closure.nil?
62
+
63
+ # top-level ivars aren't visible from within a method
64
+ # @sg-ignore Need to add nil check here
65
+ return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
66
+
67
+ # @sg-ignore Need to add nil check here
68
+ return true if viewing_closure.binder.namespace == closure.binder.namespace
69
+
70
+ # @sg-ignore Need to add nil check here
71
+ return true if viewing_closure.return_type == closure.context
72
+
73
+ return true if viewing_closure.is_a?(Pin::Namespace)
74
+
75
+ parent_of_viewing_closure = viewing_closure.closure
76
+
77
+ return false if parent_of_viewing_closure.nil?
78
+
79
+ visible_in_closure?(parent_of_viewing_closure)
80
+ end
36
81
  end
37
82
  end
38
83
  end