solargraph 0.56.2 → 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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +125 -0
  3. data/.github/workflows/plugins.yml +148 -6
  4. data/.github/workflows/rspec.yml +39 -4
  5. data/.github/workflows/typecheck.yml +5 -2
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +2627 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +42 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/lib/solargraph/api_map/cache.rb +3 -2
  16. data/lib/solargraph/api_map/constants.rb +218 -0
  17. data/lib/solargraph/api_map/index.rb +20 -26
  18. data/lib/solargraph/api_map/source_to_yard.rb +10 -4
  19. data/lib/solargraph/api_map/store.rb +126 -18
  20. data/lib/solargraph/api_map.rb +212 -234
  21. data/lib/solargraph/bench.rb +1 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +1 -0
  23. data/lib/solargraph/complex_type/unique_type.rb +7 -7
  24. data/lib/solargraph/complex_type.rb +5 -1
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  26. data/lib/solargraph/convention/base.rb +17 -0
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  29. data/lib/solargraph/convention/data_definition.rb +2 -1
  30. data/lib/solargraph/convention/gemspec.rb +1 -1
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  33. data/lib/solargraph/convention/struct_definition.rb +36 -13
  34. data/lib/solargraph/convention.rb +31 -2
  35. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  36. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
  37. data/lib/solargraph/doc_map.rb +40 -12
  38. data/lib/solargraph/environ.rb +9 -2
  39. data/lib/solargraph/gem_pins.rb +17 -11
  40. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  41. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  42. data/lib/solargraph/language_server/host.rb +2 -1
  43. data/lib/solargraph/language_server/message/base.rb +2 -1
  44. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  45. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  48. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  49. data/lib/solargraph/language_server/progress.rb +8 -0
  50. data/lib/solargraph/language_server/request.rb +1 -0
  51. data/lib/solargraph/library.rb +8 -15
  52. data/lib/solargraph/location.rb +2 -0
  53. data/lib/solargraph/logging.rb +11 -2
  54. data/lib/solargraph/page.rb +4 -0
  55. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  56. data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -4
  57. data/lib/solargraph/parser/node_methods.rb +2 -2
  58. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  59. data/lib/solargraph/parser/node_processor.rb +6 -2
  60. data/lib/solargraph/parser/parser_gem/class_methods.rb +1 -1
  61. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  62. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  63. data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
  64. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
  68. data/lib/solargraph/parser/region.rb +3 -0
  69. data/lib/solargraph/parser/snippet.rb +2 -0
  70. data/lib/solargraph/pin/base.rb +50 -8
  71. data/lib/solargraph/pin/base_variable.rb +1 -2
  72. data/lib/solargraph/pin/callable.rb +9 -0
  73. data/lib/solargraph/pin/closure.rb +2 -0
  74. data/lib/solargraph/pin/common.rb +6 -2
  75. data/lib/solargraph/pin/constant.rb +2 -0
  76. data/lib/solargraph/pin/delegated_method.rb +1 -0
  77. data/lib/solargraph/pin/local_variable.rb +4 -1
  78. data/lib/solargraph/pin/method.rb +8 -5
  79. data/lib/solargraph/pin/method_alias.rb +3 -0
  80. data/lib/solargraph/pin/parameter.rb +18 -8
  81. data/lib/solargraph/pin/proxy_type.rb +1 -0
  82. data/lib/solargraph/pin/reference/override.rb +15 -1
  83. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  84. data/lib/solargraph/pin/reference.rb +26 -0
  85. data/lib/solargraph/pin/search.rb +3 -1
  86. data/lib/solargraph/pin/signature.rb +2 -0
  87. data/lib/solargraph/pin/symbol.rb +5 -0
  88. data/lib/solargraph/pin_cache.rb +64 -4
  89. data/lib/solargraph/position.rb +2 -0
  90. data/lib/solargraph/range.rb +1 -0
  91. data/lib/solargraph/rbs_map/conversions.rb +7 -5
  92. data/lib/solargraph/rbs_map/core_map.rb +3 -0
  93. data/lib/solargraph/rbs_map.rb +15 -2
  94. data/lib/solargraph/shell.rb +3 -0
  95. data/lib/solargraph/source/chain/link.rb +10 -1
  96. data/lib/solargraph/source/chain.rb +9 -2
  97. data/lib/solargraph/source/change.rb +2 -2
  98. data/lib/solargraph/source/cursor.rb +2 -3
  99. data/lib/solargraph/source/source_chainer.rb +1 -1
  100. data/lib/solargraph/source.rb +5 -2
  101. data/lib/solargraph/source_map/clip.rb +1 -1
  102. data/lib/solargraph/source_map/data.rb +4 -0
  103. data/lib/solargraph/source_map/mapper.rb +4 -2
  104. data/lib/solargraph/source_map.rb +21 -14
  105. data/lib/solargraph/type_checker/param_def.rb +2 -0
  106. data/lib/solargraph/type_checker/rules.rb +8 -0
  107. data/lib/solargraph/type_checker.rb +173 -120
  108. data/lib/solargraph/version.rb +1 -1
  109. data/lib/solargraph/workspace/config.rb +0 -2
  110. data/lib/solargraph/workspace/require_paths.rb +98 -0
  111. data/lib/solargraph/workspace.rb +16 -48
  112. data/lib/solargraph/yard_map/mapper/to_method.rb +2 -2
  113. data/lib/solargraph/yardoc.rb +16 -3
  114. data/lib/solargraph.rb +2 -0
  115. data/rbs/fills/tuple.rbs +2 -3
  116. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  117. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  118. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  119. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  120. data/solargraph.gemspec +14 -4
  121. metadata +123 -9
  122. data/lib/.rubocop.yml +0 -22
@@ -37,6 +37,7 @@ module Solargraph
37
37
  .to_h
38
38
  end
39
39
 
40
+ # @return [Set<SourceMap>]
40
41
  def icebox
41
42
  @icebox ||= (source_maps - [live_map])
42
43
  end
@@ -130,6 +130,7 @@ module Solargraph
130
130
  end.call
131
131
  end
132
132
 
133
+ # @return [self]
133
134
  def namespace_type
134
135
  return ComplexType.parse('::Object') if duck_type?
135
136
  return ComplexType.parse('::NilClass') if nil_type?
@@ -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<UniqueType>, nil]
356
+ # @param new_key_types [Array<ComplexType>, nil]
357
357
  # @param rooted [Boolean, nil]
358
- # @param new_subtypes [Array<UniqueType>, nil]
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
@@ -22,6 +22,7 @@ module Solargraph
22
22
  # s(:def, :foo,
23
23
  # s(:args),
24
24
  # s(:send, nil, :bar))))
25
+ # @param node [::Parser::AST::Node]
25
26
  def match?(node)
26
27
  return false unless node&.type == :casgn
27
28
  return false if node.children[2].nil?
@@ -25,6 +25,8 @@ module Solargraph
25
25
  # s(:def, :foo,
26
26
  # s(:args),
27
27
  # s(:send, nil, :bar)))
28
+ #
29
+ # @param node [Parser::AST::Node]
28
30
  def match?(node)
29
31
  return false unless node&.type == :class
30
32
 
@@ -46,7 +48,7 @@ module Solargraph
46
48
  end
47
49
  end
48
50
 
49
- # @return [Parser::AST::Node]
51
+ # @param node [Parser::AST::Node]
50
52
  def initialize(node)
51
53
  @node = node
52
54
  end
@@ -35,7 +35,7 @@ module Solargraph
35
35
  comments: comments_for(node)
36
36
  )
37
37
 
38
- # TODO: Support both arg and kwarg initializers for Data.define
38
+ # @todo Support both arg and kwarg initializers for Data.define
39
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
40
  pins.push initialize_method_pin
41
41
 
@@ -88,6 +88,7 @@ module Solargraph
88
88
  end
89
89
 
90
90
  # @param attribute_node [Parser::AST::Node]
91
+ # @param attribute_name [String]
91
92
  # @return [String, nil]
92
93
  def attribute_comments(attribute_node, attribute_name)
93
94
  data_comments = comments_for(attribute_node)
@@ -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: [
@@ -22,6 +22,7 @@ module Solargraph
22
22
  # s(:def, :foo,
23
23
  # s(:args),
24
24
  # s(:send, nil, :bar))))
25
+ # @param node [Parser::AST::Node]
25
26
  def match?(node)
26
27
  return false unless node&.type == :casgn
27
28
  return false if node.children[2].nil?
@@ -25,6 +25,8 @@ module Solargraph
25
25
  # s(:def, :foo,
26
26
  # s(:args),
27
27
  # s(:send, nil, :bar)))
28
+ #
29
+ # @param node [Parser::AST::Node]
28
30
  def match?(node)
29
31
  return false unless node&.type == :class
30
32
 
@@ -46,7 +48,7 @@ module Solargraph
46
48
  end
47
49
  end
48
50
 
49
- # @return [Parser::AST::Node]
51
+ # @param node [Parser::AST::Node]
50
52
  def initialize(node)
51
53
  @node = node
52
54
  end
@@ -20,7 +20,8 @@ module Solargraph
20
20
  name: struct_definition_node.class_name,
21
21
  docstring: docstring,
22
22
  visibility: :public,
23
- gates: region.closure.gates.freeze
23
+ gates: region.closure.gates.freeze,
24
+ source: :struct_definition
24
25
  )
25
26
  pins.push nspin
26
27
 
@@ -32,7 +33,8 @@ module Solargraph
32
33
  location: get_node_location(node),
33
34
  closure: nspin,
34
35
  visibility: :private,
35
- docstring: docstring
36
+ docstring: docstring,
37
+ source: :struct_definition
36
38
  )
37
39
 
38
40
  pins.push initialize_method_pin
@@ -43,7 +45,8 @@ module Solargraph
43
45
  name: attribute_name,
44
46
  decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
45
47
  location: get_node_location(attribute_node),
46
- closure: initialize_method_pin
48
+ closure: initialize_method_pin,
49
+ source: :struct_definition
47
50
  )
48
51
  )
49
52
  end
@@ -53,29 +56,40 @@ module Solargraph
53
56
  [attribute_name, "#{attribute_name}="].each do |name|
54
57
  docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
55
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
+
56
63
  method_pin = Pin::Method.new(
57
64
  name: name,
58
65
  parameters: [],
59
66
  scope: :instance,
60
67
  location: get_node_location(attribute_node),
61
68
  closure: nspin,
69
+ docstring: YARD::Docstring.new(return_type_comment),
62
70
  # even assignments return the value
63
- comments: attribute_comment(docs, false),
64
- visibility: :public
71
+ comments: return_type_comment,
72
+ return_type: attribute_type,
73
+ visibility: :public,
74
+ source: :struct_definition
65
75
  )
66
76
 
67
77
  if name.end_with?('=')
68
78
  method_pin.parameters << Pin::Parameter.new(
69
79
  name: attribute_name,
70
80
  location: get_node_location(attribute_node),
71
- closure: nspin,
72
- comments: attribute_comment(docs, true)
81
+ closure: method_pin,
82
+ return_type: attribute_type,
83
+ comments: param_comment,
84
+ source: :struct_definition
73
85
  )
74
86
 
75
87
  pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
76
- closure: method_pin,
77
- location: get_node_location(attribute_node),
78
- comments: attribute_comment(docs, false))
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)
79
93
  end
80
94
 
81
95
  pins.push method_pin
@@ -88,7 +102,7 @@ module Solargraph
88
102
 
89
103
  private
90
104
 
91
- # @return [StructDefintionNode, nil]
105
+ # @return [StructDefintionNode, StructAssignmentNode, nil]
92
106
  def struct_definition_node
93
107
  @struct_definition_node ||= if StructDefintionNode.match?(node)
94
108
  StructDefintionNode.new(node)
@@ -113,7 +127,7 @@ module Solargraph
113
127
 
114
128
  # We should support specific comments for an attribute, and that can be either a @return on an @param
115
129
  # But since we merge into the struct_comments, then we should interpret either as a param
116
- comment = '@param ' + attr_name + comment[7..] if comment.start_with?('@return')
130
+ comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return')
117
131
 
118
132
  struct_comments += "\n#{comment}"
119
133
  end
@@ -121,12 +135,21 @@ module Solargraph
121
135
  Solargraph::Source.parse_docstring(struct_comments).to_docstring
122
136
  end
123
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
+
124
145
  # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op
125
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
126
149
  def attribute_comment(tag, for_setter)
127
150
  return "" if tag.nil?
128
151
 
129
- suffix = "[#{tag.types&.join(',') || 'undefined'}] #{tag.text}"
152
+ suffix = "[#{tag_string(tag)}] #{tag.text}"
130
153
 
131
154
  if for_setter
132
155
  "@param #{tag.name} #{suffix}"
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Solargraph
5
4
  # Conventions provide a way to modify an ApiMap based on expectations about
6
5
  # one of its sources.
@@ -12,6 +11,7 @@ module Solargraph
12
11
  autoload :Rakefile, 'solargraph/convention/rakefile'
13
12
  autoload :StructDefinition, 'solargraph/convention/struct_definition'
14
13
  autoload :DataDefinition, 'solargraph/convention/data_definition'
14
+ autoload :ActiveSupportConcern, 'solargraph/convention/active_support_concern'
15
15
 
16
16
  # @type [Set<Convention::Base>]
17
17
  @@conventions = Set.new
@@ -22,6 +22,12 @@ module Solargraph
22
22
  @@conventions.add convention.new
23
23
  end
24
24
 
25
+ # @param convention [Class<Convention::Base>]
26
+ # @return [void]
27
+ def self.unregister convention
28
+ @@conventions.delete_if { |c| c.is_a?(convention) }
29
+ end
30
+
25
31
  # @param source_map [SourceMap]
26
32
  # @return [Environ]
27
33
  def self.for_local(source_map)
@@ -32,7 +38,7 @@ module Solargraph
32
38
  result
33
39
  end
34
40
 
35
- # @param yard_map [DocMap]
41
+ # @param doc_map [DocMap]
36
42
  # @return [Environ]
37
43
  def self.for_global(doc_map)
38
44
  result = Environ.new
@@ -42,8 +48,31 @@ module Solargraph
42
48
  result
43
49
  end
44
50
 
51
+ # Provides any additional method pins based on the described object.
52
+ #
53
+ # @param api_map [ApiMap]
54
+ # @param rooted_tag [String] A fully qualified namespace, with
55
+ # generic parameter values if applicable
56
+ # @param scope [Symbol] :class or :instance
57
+ # @param visibility [Array<Symbol>] :public, :protected, and/or :private
58
+ # @param deep [Boolean]
59
+ # @param skip [Set<String>]
60
+ # @param no_core [Boolean] Skip core classes if true
61
+ #
62
+ # @return [Environ]
63
+ def self.for_object api_map, rooted_tag, scope, visibility,
64
+ deep, skip, no_core
65
+ result = Environ.new
66
+ @@conventions.each do |conv|
67
+ result.merge conv.object(api_map, rooted_tag, scope, visibility,
68
+ deep, skip, no_core)
69
+ end
70
+ result
71
+ end
72
+
45
73
  register Gemfile
46
74
  register Gemspec
47
75
  register Rakefile
76
+ register ActiveSupportConcern
48
77
  end
49
78
  end
@@ -28,7 +28,12 @@ module Solargraph
28
28
  options, paths = generate_options(source.filename, source.code)
29
29
  store = RuboCop::ConfigStore.new
30
30
  runner = RuboCop::Runner.new(options, store)
31
- result = redirect_stdout{ runner.run(paths) }
31
+ # Ensure only one instance of RuboCop::Runner is running at
32
+ # a time - it uses 'chdir' to read config files with ERB,
33
+ # which can conflict with other chdirs.
34
+ result = Solargraph::CHDIR_MUTEX.synchronize do
35
+ redirect_stdout{ runner.run(paths) }
36
+ end
32
37
 
33
38
  return [] if result.empty?
34
39
 
@@ -15,10 +15,10 @@ module Solargraph
15
15
  # @return [void]
16
16
  def require_rubocop(version = nil)
17
17
  begin
18
+ # @type [String]
18
19
  gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
19
20
  gem_lib_path = File.join(gem_path, 'lib')
20
21
  $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
21
- # @todo Gem::MissingSpecVersionError is undocumented for some reason
22
22
  # @sg-ignore
23
23
  rescue Gem::MissingSpecVersionError => e
24
24
  raise InvalidRubocopVersionError,