solargraph 0.56.1 → 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 (132) 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 +50 -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 +61 -0
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  29. data/lib/solargraph/convention/data_definition.rb +105 -0
  30. data/lib/solargraph/convention/gemspec.rb +3 -2
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
  33. data/lib/solargraph/convention/struct_definition.rb +87 -24
  34. data/lib/solargraph/convention.rb +32 -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 +17 -24
  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 +10 -5
  59. data/lib/solargraph/parser/node_processor.rb +24 -8
  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/casgn_node.rb +1 -21
  66. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  69. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +1 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +1 -0
  72. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
  73. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  75. data/lib/solargraph/parser/region.rb +3 -0
  76. data/lib/solargraph/parser/snippet.rb +2 -0
  77. data/lib/solargraph/pin/base.rb +65 -8
  78. data/lib/solargraph/pin/base_variable.rb +1 -2
  79. data/lib/solargraph/pin/callable.rb +9 -0
  80. data/lib/solargraph/pin/closure.rb +2 -0
  81. data/lib/solargraph/pin/common.rb +6 -2
  82. data/lib/solargraph/pin/constant.rb +2 -0
  83. data/lib/solargraph/pin/delegated_method.rb +1 -0
  84. data/lib/solargraph/pin/local_variable.rb +4 -1
  85. data/lib/solargraph/pin/method.rb +12 -7
  86. data/lib/solargraph/pin/method_alias.rb +3 -0
  87. data/lib/solargraph/pin/parameter.rb +18 -8
  88. data/lib/solargraph/pin/proxy_type.rb +1 -0
  89. data/lib/solargraph/pin/reference/override.rb +15 -1
  90. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  91. data/lib/solargraph/pin/reference.rb +26 -0
  92. data/lib/solargraph/pin/search.rb +3 -1
  93. data/lib/solargraph/pin/signature.rb +2 -0
  94. data/lib/solargraph/pin/symbol.rb +5 -0
  95. data/lib/solargraph/pin_cache.rb +64 -4
  96. data/lib/solargraph/position.rb +2 -0
  97. data/lib/solargraph/range.rb +1 -0
  98. data/lib/solargraph/rbs_map/conversions.rb +47 -18
  99. data/lib/solargraph/rbs_map/core_map.rb +3 -0
  100. data/lib/solargraph/rbs_map.rb +15 -2
  101. data/lib/solargraph/shell.rb +3 -0
  102. data/lib/solargraph/source/chain/link.rb +10 -1
  103. data/lib/solargraph/source/chain.rb +9 -2
  104. data/lib/solargraph/source/change.rb +2 -2
  105. data/lib/solargraph/source/cursor.rb +2 -3
  106. data/lib/solargraph/source/source_chainer.rb +1 -1
  107. data/lib/solargraph/source.rb +5 -2
  108. data/lib/solargraph/source_map/clip.rb +1 -1
  109. data/lib/solargraph/source_map/data.rb +4 -0
  110. data/lib/solargraph/source_map/mapper.rb +4 -2
  111. data/lib/solargraph/source_map.rb +21 -14
  112. data/lib/solargraph/type_checker/param_def.rb +2 -0
  113. data/lib/solargraph/type_checker/rules.rb +8 -0
  114. data/lib/solargraph/type_checker.rb +173 -120
  115. data/lib/solargraph/version.rb +1 -1
  116. data/lib/solargraph/workspace/config.rb +1 -3
  117. data/lib/solargraph/workspace/require_paths.rb +98 -0
  118. data/lib/solargraph/workspace.rb +16 -48
  119. data/lib/solargraph/yard_map/helpers.rb +29 -1
  120. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  121. data/lib/solargraph/yard_map/mapper/to_method.rb +3 -8
  122. data/lib/solargraph/yard_map/mapper/to_namespace.rb +7 -7
  123. data/lib/solargraph/yardoc.rb +16 -3
  124. data/lib/solargraph.rb +15 -0
  125. data/rbs/fills/tuple.rbs +2 -3
  126. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  127. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  128. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  129. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  130. data/solargraph.gemspec +14 -4
  131. metadata +126 -9
  132. data/lib/.rubocop.yml +0 -22
@@ -8,8 +8,9 @@ module Solargraph
8
8
 
9
9
  module NodeProcessors
10
10
  class StructNode < Parser::NodeProcessor::Base
11
+ # @return [Boolean] continue processing the next processor of the same node.
11
12
  def process
12
- return if struct_definition_node.nil?
13
+ return true if struct_definition_node.nil?
13
14
 
14
15
  loc = get_node_location(node)
15
16
  nspin = Solargraph::Pin::Namespace.new(
@@ -17,9 +18,10 @@ module Solargraph
17
18
  location: loc,
18
19
  closure: region.closure,
19
20
  name: struct_definition_node.class_name,
20
- comments: comments_for(node),
21
+ docstring: docstring,
21
22
  visibility: :public,
22
- gates: region.closure.gates.freeze
23
+ gates: region.closure.gates.freeze,
24
+ source: :struct_definition
23
25
  )
24
26
  pins.push nspin
25
27
 
@@ -31,7 +33,8 @@ module Solargraph
31
33
  location: get_node_location(node),
32
34
  closure: nspin,
33
35
  visibility: :private,
34
- comments: comments_for(node)
36
+ docstring: docstring,
37
+ source: :struct_definition
35
38
  )
36
39
 
37
40
  pins.push initialize_method_pin
@@ -42,7 +45,8 @@ module Solargraph
42
45
  name: attribute_name,
43
46
  decl: struct_definition_node.keyword_init? ? :kwarg : :arg,
44
47
  location: get_node_location(attribute_node),
45
- closure: initialize_method_pin
48
+ closure: initialize_method_pin,
49
+ source: :struct_definition
46
50
  )
47
51
  )
48
52
  end
@@ -50,49 +54,108 @@ module Solargraph
50
54
  # define attribute accessors and instance variables
51
55
  struct_definition_node.attributes.each do |attribute_node, attribute_name|
52
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
+
53
63
  method_pin = Pin::Method.new(
54
64
  name: name,
55
65
  parameters: [],
56
66
  scope: :instance,
57
67
  location: get_node_location(attribute_node),
58
68
  closure: nspin,
59
- comments: attribute_comments(attribute_node, attribute_name),
60
- visibility: :public
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
61
75
  )
62
76
 
63
- pins.push method_pin
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
+ )
64
86
 
65
- next unless name.include?('=') # setter
66
- pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
67
- closure: method_pin,
68
- location: get_node_location(attribute_node),
69
- comments: attribute_comments(attribute_node, attribute_name))
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
70
96
  end
71
97
  end
72
98
 
73
99
  process_children region.update(closure: nspin, visibility: :public)
100
+ false
74
101
  end
75
102
 
76
103
  private
77
104
 
78
- # @return [StructDefintionNode, nil]
105
+ # @return [StructDefintionNode, StructAssignmentNode, nil]
79
106
  def struct_definition_node
80
- @struct_definition_node ||= if StructDefintionNode.valid?(node)
107
+ @struct_definition_node ||= if StructDefintionNode.match?(node)
81
108
  StructDefintionNode.new(node)
82
- elsif StructAssignmentNode.valid?(node)
109
+ elsif StructAssignmentNode.match?(node)
83
110
  StructAssignmentNode.new(node)
84
111
  end
85
112
  end
86
113
 
87
- # @param attribute_node [Parser::AST::Node]
88
- # @return [String, nil]
89
- def attribute_comments(attribute_node, attribute_name)
90
- struct_comments = comments_for(attribute_node)
91
- return if struct_comments.nil? || struct_comments.empty?
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?
92
127
 
93
- struct_comments.split("\n").find do |row|
94
- row.include?(attribute_name)
95
- end&.gsub('@param', '@return')&.gsub(attribute_name, '')
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
96
159
  end
97
160
  end
98
161
  end
@@ -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.
@@ -11,6 +10,8 @@ module Solargraph
11
10
  autoload :Gemspec, 'solargraph/convention/gemspec'
12
11
  autoload :Rakefile, 'solargraph/convention/rakefile'
13
12
  autoload :StructDefinition, 'solargraph/convention/struct_definition'
13
+ autoload :DataDefinition, 'solargraph/convention/data_definition'
14
+ autoload :ActiveSupportConcern, 'solargraph/convention/active_support_concern'
14
15
 
15
16
  # @type [Set<Convention::Base>]
16
17
  @@conventions = Set.new
@@ -21,6 +22,12 @@ module Solargraph
21
22
  @@conventions.add convention.new
22
23
  end
23
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
+
24
31
  # @param source_map [SourceMap]
25
32
  # @return [Environ]
26
33
  def self.for_local(source_map)
@@ -31,7 +38,7 @@ module Solargraph
31
38
  result
32
39
  end
33
40
 
34
- # @param yard_map [DocMap]
41
+ # @param doc_map [DocMap]
35
42
  # @return [Environ]
36
43
  def self.for_global(doc_map)
37
44
  result = Environ.new
@@ -41,8 +48,31 @@ module Solargraph
41
48
  result
42
49
  end
43
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
+
44
73
  register Gemfile
45
74
  register Gemspec
46
75
  register Rakefile
76
+ register ActiveSupportConcern
47
77
  end
48
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,
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'pathname'
4
4
  require 'benchmark'
5
+ require 'open3'
5
6
 
6
7
  module Solargraph
7
8
  # A collection of pins generated from required gems.
@@ -32,8 +33,10 @@ module Solargraph
32
33
  # @return [Array<Gem::Specification>]
33
34
  attr_reader :uncached_rbs_collection_gemspecs
34
35
 
36
+ # @return [String, nil]
35
37
  attr_reader :rbs_collection_path
36
38
 
39
+ # @return [String, nil]
37
40
  attr_reader :rbs_collection_config_path
38
41
 
39
42
  # @return [Workspace, nil]
@@ -52,10 +55,13 @@ module Solargraph
52
55
  @rbs_collection_path = workspace&.rbs_collection_path
53
56
  @rbs_collection_config_path = workspace&.rbs_collection_config_path
54
57
  @environ = Convention.for_global(self)
58
+ @requires.concat @environ.requires if @environ
55
59
  load_serialized_gem_pins
56
60
  pins.concat @environ.pins
57
61
  end
58
62
 
63
+ # @param out [IO]
64
+ # @return [void]
59
65
  def cache_all!(out)
60
66
  # if we log at debug level:
61
67
  if logger.info?
@@ -73,12 +79,18 @@ module Solargraph
73
79
  @uncached_yard_gemspecs = []
74
80
  end
75
81
 
82
+ # @param gemspec [Gem::Specification]
83
+ # @param out [IO]
84
+ # @return [void]
76
85
  def cache_yard_pins(gemspec, out)
77
- pins = GemPins.build_yard_pins(gemspec)
86
+ pins = GemPins.build_yard_pins(yard_plugins, gemspec)
78
87
  PinCache.serialize_yard_gem(gemspec, pins)
79
88
  logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
80
89
  end
81
90
 
91
+ # @param gemspec [Gem::Specification]
92
+ # @param out [IO]
93
+ # @return [void]
82
94
  def cache_rbs_collection_pins(gemspec, out)
83
95
  rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
84
96
  pins = rbs_map.pins
@@ -90,6 +102,9 @@ module Solargraph
90
102
  end
91
103
 
92
104
  # @param gemspec [Gem::Specification]
105
+ # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
106
+ # @param out [IO, nil] output stream for logging
107
+ # @return [void]
93
108
  def cache(gemspec, rebuild: false, out: nil)
94
109
  build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild
95
110
  build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
@@ -113,30 +128,42 @@ module Solargraph
113
128
  @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
114
129
  end
115
130
 
131
+ # @return [Hash{Array(String, String) => Array<Gem::Specification>}] Indexed by gemspec name and version
116
132
  def self.all_yard_gems_in_memory
117
133
  @yard_gems_in_memory ||= {}
118
134
  end
119
135
 
136
+ # @return [Hash{String => Hash{Array(String, String) => Array<Pin::Base>}}] stored by RBS collection path
120
137
  def self.all_rbs_collection_gems_in_memory
121
138
  @rbs_collection_gems_in_memory ||= {}
122
139
  end
123
140
 
141
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
124
142
  def yard_pins_in_memory
125
143
  self.class.all_yard_gems_in_memory
126
144
  end
127
145
 
146
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
128
147
  def rbs_collection_pins_in_memory
129
148
  self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
130
149
  end
131
150
 
151
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
132
152
  def self.all_combined_pins_in_memory
133
153
  @combined_pins_in_memory ||= {}
134
154
  end
135
155
 
156
+ # @todo this should also include an index by the hash of the RBS collection
157
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
136
158
  def combined_pins_in_memory
137
159
  self.class.all_combined_pins_in_memory
138
160
  end
139
161
 
162
+ # @return [Array<String>]
163
+ def yard_plugins
164
+ @environ.yard_plugins
165
+ end
166
+
140
167
  # @return [Set<Gem::Specification>]
141
168
  def dependencies
142
169
  @dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
@@ -150,7 +177,11 @@ module Solargraph
150
177
  @uncached_yard_gemspecs = []
151
178
  @uncached_rbs_collection_gemspecs = []
152
179
  with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
180
+ # @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash<Array(String, Array<Gem::Specification>), undefined>, received Array<Array(String, Array<Gem::Specification>)>
181
+ # @type [Array<String>]
153
182
  paths = Hash[without_gemspecs].keys
183
+ # @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash<Array(String, Array<Gem::Specification>), undefined>, received Array<Array(String, Array<Gem::Specification>)>
184
+ # @type [Array<Gem::Specification>]
154
185
  gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a
155
186
 
156
187
  paths.each do |path|
@@ -259,6 +290,8 @@ module Solargraph
259
290
  end
260
291
  end
261
292
 
293
+ # @param gemspec [Gem::Specification]
294
+ # @param rbs_version_cache_key [String]
262
295
  # @return [Array<Pin::Base>, nil]
263
296
  def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
264
297
  return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
@@ -274,22 +307,13 @@ module Solargraph
274
307
  end
275
308
  end
276
309
 
277
- # @param gemspec [Gem::Specification]
278
- # @return [Boolean]
279
- def try_gem_in_memory gemspec
280
- gempins = DocMap.gems_in_memory[gemspec]
281
- return false unless gempins
282
- Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
283
- @pins.concat gempins
284
- true
285
- end
286
-
287
310
  # @param path [String]
288
311
  # @return [::Array<Gem::Specification>, nil]
289
312
  def resolve_path_to_gemspecs path
290
313
  return nil if path.empty?
291
314
  return gemspecs_required_from_bundler if path == 'bundler/require'
292
315
 
316
+ # @type [Gem::Specification, nil]
293
317
  gemspec = Gem::Specification.find_by_path(path)
294
318
  if gemspec.nil?
295
319
  gem_name_guess = path.split('/').first
@@ -313,10 +337,12 @@ module Solargraph
313
337
  # @param gemspec [Gem::Specification]
314
338
  # @return [Gem::Specification]
315
339
  def gemspec_or_preference gemspec
340
+ # :nocov: dormant feature
316
341
  return gemspec unless preference_map.key?(gemspec.name)
317
342
  return gemspec if gemspec.version == preference_map[gemspec.name].version
318
343
 
319
- change_gemspec_version gemspec, preference_map[by_path.name].version
344
+ change_gemspec_version gemspec, preference_map[gemspec.name].version
345
+ # :nocov:
320
346
  end
321
347
 
322
348
  # @param gemspec [Gem::Specification]
@@ -355,6 +381,7 @@ module Solargraph
355
381
  self.class.inspect
356
382
  end
357
383
 
384
+ # @return [Array<Gem::Specification>]
358
385
  def gemspecs_required_from_bundler
359
386
  # @todo Handle projects with custom Bundler/Gemfile setups
360
387
  return unless workspace.gemfile?
@@ -377,6 +404,7 @@ module Solargraph
377
404
  end
378
405
  end
379
406
 
407
+ # @return [Array<Gem::Specification>]
380
408
  def gemspecs_required_from_external_bundle
381
409
  logger.info 'Fetching gemspecs required from external bundle'
382
410
  return [] unless workspace&.directory
@@ -13,16 +13,21 @@ module Solargraph
13
13
  # @return [Array<String>]
14
14
  attr_reader :domains
15
15
 
16
- # @return [Array<Pin::Reference::Override>]
16
+ # @return [Array<Pin::Base>]
17
17
  attr_reader :pins
18
18
 
19
+ # @return [Array<String>]
20
+ attr_reader :yard_plugins
21
+
19
22
  # @param requires [Array<String>]
20
23
  # @param domains [Array<String>]
21
24
  # @param pins [Array<Pin::Base>]
22
- def initialize requires: [], domains: [], pins: []
25
+ # @param yard_plugins[Array<String>]
26
+ def initialize requires: [], domains: [], pins: [], yard_plugins: []
23
27
  @requires = requires
24
28
  @domains = domains
25
29
  @pins = pins
30
+ @yard_plugins = yard_plugins
26
31
  end
27
32
 
28
33
  # @return [self]
@@ -30,6 +35,7 @@ module Solargraph
30
35
  domains.clear
31
36
  requires.clear
32
37
  pins.clear
38
+ yard_plugins.clear
33
39
  self
34
40
  end
35
41
 
@@ -39,6 +45,7 @@ module Solargraph
39
45
  domains.concat other.domains
40
46
  requires.concat other.requires
41
47
  pins.concat other.pins
48
+ yard_plugins.concat other.yard_plugins
42
49
  self
43
50
  end
44
51
  end
@@ -11,17 +11,9 @@ module Solargraph
11
11
  include Logging
12
12
  end
13
13
 
14
- # @param gemspec [Gem::Specification]
15
- # @return [Array<Pin::Base>]
16
- def self.build_yard_pins(gemspec)
17
- Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
18
- yardoc = Yardoc.load!(gemspec)
19
- YardMap::Mapper.new(yardoc, gemspec).map
20
- end
21
-
22
14
  # @param pins [Array<Pin::Base>]
15
+ # @return [Array<Pin::Base>]
23
16
  def self.combine_method_pins_by_path(pins)
24
- # bad_pins = pins.select { |pin| pin.is_a?(Pin::Method) && pin.path == 'StringIO.open' && pin.source == :rbs }; raise "wtf: #{bad_pins}" if bad_pins.length > 1
25
17
  method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method }
26
18
  by_path = method_pins.group_by(&:path)
27
19
  by_path.transform_values! do |pins|
@@ -30,8 +22,12 @@ module Solargraph
30
22
  by_path.values + alias_pins
31
23
  end
32
24
 
25
+ # @param pins [Array<Pin::Method>]
26
+ # @return [Pin::Method, nil]
33
27
  def self.combine_method_pins(*pins)
34
- out = pins.reduce(nil) do |memo, pin|
28
+ # @type [Pin::Method, nil]
29
+ combined_pin = nil
30
+ out = pins.reduce(combined_pin) do |memo, pin|
35
31
  next pin if memo.nil?
36
32
  if memo == pin && memo.source != :combined
37
33
  # @todo we should track down situations where we are handled
@@ -45,8 +41,18 @@ module Solargraph
45
41
  out
46
42
  end
47
43
 
44
+ # @param yard_plugins [Array<String>] The names of YARD plugins to use.
45
+ # @param gemspec [Gem::Specification]
46
+ # @return [Array<Pin::Base>]
47
+ def self.build_yard_pins(yard_plugins, gemspec)
48
+ Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec)
49
+ yardoc = Yardoc.load!(gemspec)
50
+ YardMap::Mapper.new(yardoc, gemspec).map
51
+ end
52
+
48
53
  # @param yard_pins [Array<Pin::Base>]
49
- # @param rbs_map [RbsMap]
54
+ # @param rbs_pins [Array<Pin::Base>]
55
+ #
50
56
  # @return [Array<Pin::Base>]
51
57
  def self.combine(yard_pins, rbs_pins)
52
58
  in_yard = Set.new
@@ -95,6 +95,7 @@ module Solargraph
95
95
  nil
96
96
  end
97
97
 
98
+ # @return [Hash{String => undefined}]
98
99
  def options
99
100
  @options ||= {}.freeze
100
101
  end
@@ -118,6 +119,7 @@ module Solargraph
118
119
  end
119
120
 
120
121
  # @param library [Solargraph::Library]
122
+ # @param progress [Solargraph::LanguageServer::Progress, nil]
121
123
  # @return [void]
122
124
  def update progress
123
125
  progress&.send(self)
@@ -72,10 +72,12 @@ module Solargraph
72
72
 
73
73
  private
74
74
 
75
+ # @return [Hash, nil]
75
76
  def next_message
76
77
  cancel_message || next_priority
77
78
  end
78
79
 
80
+ # @return [Hash, nil]
79
81
  def cancel_message
80
82
  # Handle cancellations first
81
83
  idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
@@ -86,6 +88,7 @@ module Solargraph
86
88
  msg
87
89
  end
88
90
 
91
+ # @return [Hash, nil]
89
92
  def next_priority
90
93
  # Prioritize updates and version-dependent messages for performance
91
94
  idx = messages.find_index do |msg|
@@ -299,6 +299,7 @@ module Solargraph
299
299
  end
300
300
  end
301
301
 
302
+ # @return [String]
302
303
  def command_path
303
304
  options['commandPath'] || 'solargraph'
304
305
  end
@@ -716,7 +717,7 @@ module Solargraph
716
717
  # A hash of client requests by ID. The host uses this to keep track of
717
718
  # pending responses.
718
719
  #
719
- # @return [Hash{Integer => Solargraph::LanguageServer::Host}]
720
+ # @return [Hash{Integer => Solargraph::LanguageServer::Request}]
720
721
  def requests
721
722
  @requests ||= {}
722
723
  end
@@ -16,7 +16,7 @@ module Solargraph
16
16
  # @return [String]
17
17
  attr_reader :method
18
18
 
19
- # @return [Hash{String => Array<undefined>, Hash{String => undefined}, String, Integer}]
19
+ # @return [Hash{String => undefined}]
20
20
  attr_reader :params
21
21
 
22
22
  # @return [Hash, Array, nil]
@@ -79,6 +79,7 @@ module Solargraph
79
79
 
80
80
  private
81
81
 
82
+ # @return [void]
82
83
  def accept_or_cancel
83
84
  if host.cancel?(id)
84
85
  # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
@@ -83,7 +83,7 @@ module Solargraph
83
83
  @fetched = true
84
84
  begin
85
85
  @available ||= begin
86
- # @sg-ignore
86
+ # @sg-ignore Variable type could not be inferred for tuple
87
87
  # @type [Gem::Dependency, nil]
88
88
  tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
89
89
  if tuple.nil?
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>]
13
14
  def code_location
14
15
  suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
15
16
  return nil if suggestions.empty?
@@ -21,6 +22,7 @@ module Solargraph::LanguageServer::Message::TextDocument
21
22
  end
22
23
  end
23
24
 
25
+ # @return [Array<Hash>]
24
26
  def require_location
25
27
  # @todo Terrible hack
26
28
  lib = host.library_for(params['textDocument']['uri'])