docscribe 1.5.0 → 1.5.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.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pathname'
4
+ require 'yaml'
4
5
  require 'docscribe/types/signature'
5
6
  require 'docscribe/types/rbs/type_formatter'
6
7
  require 'docscribe/types/rbs/collection_loader'
@@ -42,7 +43,7 @@ module Docscribe
42
43
  # @param [Symbol, String] name method name
43
44
  # @raise [::RBS::BaseError]
44
45
  # @raise [StandardError]
45
- # @return [Docscribe::Types::MethodSignature, nil] if StandardError
46
+ # @return [Docscribe::Types::MethodSignature, nil]
46
47
  # @return [nil] if ::RBS::BaseError
47
48
  # @return [nil] if StandardError
48
49
  def signature_for(container:, scope:, name:)
@@ -105,21 +106,91 @@ module Docscribe
105
106
  # @param [Array<String>] collection_dirs RBS collection directories
106
107
  # @raise [::RBS::BaseError]
107
108
  # @raise [StandardError]
109
+ # @return [RBS::Environment]
108
110
  # @return [RBS::Environment] if ::RBS::BaseError
109
- # @return [Object] if ::RBS::BaseError
110
111
  def try_with_fallback_build_env(all_dirs, collection_dirs)
111
- build_env(all_dirs)
112
+ # First attempt: load core types + all dirs (sig + collection).
113
+ # If duplicate declarations occur (stdlib gem in both `library: 'rbs'`
114
+ # and collection), retry with individual collection gem dirs,
115
+ # skipping those already provided by the rbs stdlib.
116
+ build_env_with_collection(all_dirs, collection_dirs)
112
117
  rescue ::RBS::BaseError => e
113
118
  raise unless collection_dirs.any? && !@collection_dropped
114
119
 
115
120
  @collection_dropped = true
116
- if ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
117
- warn "Docscribe: RBS collection error (#{e.class}), dropping collection dirs. " \
118
- 'Set DOCSCRIBE_RBS_DEBUG=1 for details.'
119
- end
121
+ warn "Docscribe: RBS collection error (#{e.class}), dropping collection dirs. " \
122
+ 'Set DOCSCRIBE_RBS_DEBUG=1 for details.'
120
123
  build_env(@sig_dirs)
121
124
  end
122
125
 
126
+ # Build the environment, handling potential duplicate declarations
127
+ # between rbs stdlib and collection gems.
128
+ #
129
+ # @private
130
+ # @param [Array<String>] all_dirs combined sig and collection dirs
131
+ # @param [Array<String>] collection_dirs RBS collection directories
132
+ # @return [RBS::Environment]
133
+ def build_env_with_collection(all_dirs, collection_dirs)
134
+ loader = ::RBS::EnvironmentLoader.new
135
+ loader.add(library: 'rbs') # steep:ignore
136
+ load_stdlib_libraries!(loader)
137
+ add_dirs_to_loader!(loader, all_dirs, collection_dirs)
138
+ env = ::RBS::Environment.from_loader(loader).resolve_type_names
139
+ @builder = ::RBS::DefinitionBuilder.new(env: env)
140
+ env
141
+ end
142
+
143
+ # Add directories to the loader, handling collection dirs separately.
144
+ #
145
+ # @private
146
+ # @param [RBS::EnvironmentLoader] loader
147
+ # @param [Array<String>] all_dirs
148
+ # @param [Array<String>] collection_dirs
149
+ # @return [void]
150
+ def add_dirs_to_loader!(loader, all_dirs, collection_dirs)
151
+ stdlib = stdlib_gem_names
152
+ all_dirs.each do |dir|
153
+ path = Pathname(dir)
154
+ next unless path.directory?
155
+
156
+ if collection_dirs.include?(dir)
157
+ add_collection_gem_dirs(loader, path, stdlib)
158
+ else
159
+ loader.add(path: path)
160
+ end
161
+ end
162
+ end
163
+
164
+ # Add individual collection gem directories to the loader.
165
+ #
166
+ # @private
167
+ # @param [RBS::EnvironmentLoader] loader
168
+ # @param [Pathname] path
169
+ # @param [Array<String>] stdlib
170
+ # @return [void]
171
+ def add_collection_gem_dirs(loader, path, stdlib)
172
+ path.children.each do |child|
173
+ next unless child.directory?
174
+ next if stdlib.include?(child.basename.to_s)
175
+
176
+ loader.add(path: child)
177
+ end
178
+ end
179
+
180
+ # Names of stdlib gems bundled with the `rbs` gem.
181
+ #
182
+ # @private
183
+ # @raise [StandardError]
184
+ # @return [Array<String>]
185
+ # @return [Array] if StandardError
186
+ def stdlib_gem_names
187
+ rbs_spec = Gem::Specification.find_by_name('rbs')
188
+ stdlib_dir = File.join(rbs_spec.gem_dir, 'stdlib')
189
+ Dir.children(stdlib_dir)
190
+ rescue StandardError
191
+ []
192
+ end
193
+
123
194
  # Build an RBS environment from the given directories.
124
195
  #
125
196
  # @private
@@ -127,8 +198,8 @@ module Docscribe
127
198
  # @return [RBS::Environment]
128
199
  def build_env(dirs)
129
200
  loader = ::RBS::EnvironmentLoader.new
130
- # Load core types transitively
131
201
  loader.add(library: 'rbs') # steep:ignore
202
+ load_stdlib_libraries!(loader)
132
203
 
133
204
  dirs.each do |dir|
134
205
  path = Pathname(dir)
@@ -140,6 +211,43 @@ module Docscribe
140
211
  env
141
212
  end
142
213
 
214
+ # Load stdlib RBS libraries declared in rbs_collection.lock.yaml.
215
+ #
216
+ # Without this, RBS types defined in user sig/ files (e.g. UNIXSocket)
217
+ # fail to resolve and the entire RBS environment breaks, causing all
218
+ # type lookups to silently fall back to inference.
219
+ #
220
+ # @private
221
+ # @param [RBS::EnvironmentLoader] loader
222
+ # @raise [StandardError]
223
+ # @return [void]
224
+ # @return [nil] if StandardError
225
+ def load_stdlib_libraries!(loader)
226
+ lock_path = File.join(Dir.pwd, 'rbs_collection.lock.yaml')
227
+ return unless File.exist?(lock_path)
228
+
229
+ lock = YAML.safe_load_file(lock_path) # steep:ignore
230
+ (lock['gems'] || []).each { |gem| add_stdlib_gem(loader, gem) }
231
+ rescue StandardError => e
232
+ warn "Docscribe: Failed to parse rbs_collection.lock.yaml: #{e.message}"
233
+ end
234
+
235
+ # Add a single stdlib gem from the lock file to the loader.
236
+ #
237
+ # @private
238
+ # @param [RBS::EnvironmentLoader] loader
239
+ # @param [Object] gem gem entry from rbs_collection.lock.yaml
240
+ # @raise [StandardError]
241
+ # @return [void]
242
+ # @return [nil] if StandardError
243
+ def add_stdlib_gem(loader, gem)
244
+ return unless gem.is_a?(Hash) && gem.dig('source', 'type') == 'stdlib'
245
+
246
+ loader.add(library: gem['name']) # steep:ignore
247
+ rescue StandardError => e
248
+ warn "Docscribe: Failed to load stdlib RBS library '#{gem['name']}': #{e.message}"
249
+ end
250
+
143
251
  # Build the appropriate instance or singleton definition for a container.
144
252
  #
145
253
  # @private
@@ -147,7 +255,10 @@ module Docscribe
147
255
  # @param [Symbol] scope :instance or :class
148
256
  # @return [RBS::Definition, nil]
149
257
  def definition_for(container:, scope:)
258
+ container = container.sub(/\[.*\]/, '').sub(/<.*>/, '')
150
259
  type_name = parse_type_name(absolute_const(container))
260
+ return nil unless @builder&.env&.type_name?(type_name)
261
+
151
262
  scope == :class ? @builder&.build_singleton(type_name) : @builder&.build_instance(type_name)
152
263
  end
153
264
 
@@ -311,13 +422,12 @@ module Docscribe
311
422
  end
312
423
  end
313
424
 
314
- # Print one debug warning per provider instance when debugging is enabled.
425
+ # Print one warning per provider instance (avoiding repeated spam).
315
426
  #
316
427
  # @private
317
428
  # @param [String] msg warning message text
318
429
  # @return [void]
319
430
  def warn_once(msg)
320
- return unless ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
321
431
  return if @warned
322
432
 
323
433
  @warned = true
@@ -18,10 +18,12 @@ module Docscribe
18
18
  # Initialize
19
19
  #
20
20
  # @param [Boolean] collapse_generics whether generic container details
21
+ # @param [Boolean] collapse_object_generics collapse Object generics
21
22
  # @return [void]
22
- def initialize(collapse_generics: false)
23
+ def initialize(collapse_generics: false, collapse_object_generics: false)
23
24
  require 'rbs'
24
25
  @collapse_generics = !!collapse_generics
26
+ @collapse_object_generics = !!collapse_object_generics
25
27
  @index = {}
26
28
  @warned = false
27
29
  end
@@ -50,7 +52,7 @@ module Docscribe
50
52
  # @raise [::RBS::BaseError]
51
53
  # @raise [SyntaxError]
52
54
  # @raise [StandardError]
53
- # @return [void] if ::RBS::BaseError, SyntaxError, StandardError
55
+ # @return [void]
54
56
  # @return [nil] if LoadError
55
57
  # @return [nil] if ::RBS::BaseError, SyntaxError, StandardError
56
58
  def load_from_string(source, label:)
@@ -210,7 +212,8 @@ module Docscribe
210
212
  def format_type(type)
211
213
  Docscribe::Types::RBS::TypeFormatter.to_yard(
212
214
  type,
213
- collapse_generics: @collapse_generics
215
+ collapse_generics: @collapse_generics,
216
+ collapse_object_generics: @collapse_object_generics
214
217
  )
215
218
  end
216
219
 
@@ -220,7 +223,7 @@ module Docscribe
220
223
  # @param [String] name method name
221
224
  # @return [String]
222
225
  def normalize_container(name)
223
- name.to_s.delete_prefix('::')
226
+ name.to_s.delete_prefix('::').sub(/\[.*\]/, '').sub(/<.*>/, '')
224
227
  end
225
228
 
226
229
  # Print one debug warning per provider instance when debugging is enabled.
@@ -16,9 +16,10 @@ module Docscribe
16
16
  #
17
17
  # @param [Array<String>] rbi_dirs directories scanned recursively for
18
18
  # @param [Boolean] collapse_generics whether generic container types
19
+ # @param [Boolean] collapse_object_generics collapse Object generics
19
20
  # @return [void]
20
- def initialize(rbi_dirs:, collapse_generics: false)
21
- super(collapse_generics: collapse_generics)
21
+ def initialize(rbi_dirs:, collapse_generics: false, collapse_object_generics: false)
22
+ super(collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
22
23
 
23
24
  Array(rbi_dirs).each do |dir|
24
25
  path = Pathname(dir)
@@ -15,9 +15,10 @@ module Docscribe
15
15
  # @param [String] source Ruby source containing inline `sig` declarations
16
16
  # @param [String] file source label used in diagnostics/debug warnings
17
17
  # @param [Boolean] collapse_generics whether generic container types
18
+ # @param [Boolean] collapse_object_generics collapse Object generics
18
19
  # @return [void]
19
- def initialize(source:, file:, collapse_generics: false)
20
- super(collapse_generics: collapse_generics)
20
+ def initialize(source:, file:, collapse_generics: false, collapse_object_generics: false)
21
+ super(collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
21
22
  load_from_string(source, label: file)
22
23
  end
23
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Docscribe
4
- VERSION = '1.5.0'
4
+ VERSION = '1.5.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docscribe
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - unurgunite
@@ -151,12 +151,14 @@ dependencies:
151
151
  version: 0.9.38
152
152
  executables:
153
153
  - docscribe
154
+ - docscribe-client
154
155
  extensions: []
155
156
  extra_rdoc_files: []
156
157
  files:
157
158
  - LICENSE.txt
158
159
  - README.md
159
160
  - exe/docscribe
161
+ - exe/docscribe-client
160
162
  - lib/docscribe.rb
161
163
  - lib/docscribe/cli.rb
162
164
  - lib/docscribe/cli/check_for_comments.rb
@@ -170,6 +172,7 @@ files:
170
172
  - lib/docscribe/cli/options.rb
171
173
  - lib/docscribe/cli/rbs_gen.rb
172
174
  - lib/docscribe/cli/run.rb
175
+ - lib/docscribe/cli/server.rb
173
176
  - lib/docscribe/cli/sigs.rb
174
177
  - lib/docscribe/cli/update_types.rb
175
178
  - lib/docscribe/config.rb
@@ -197,6 +200,7 @@ files:
197
200
  - lib/docscribe/inline_rewriter/doc_builder.rb
198
201
  - lib/docscribe/inline_rewriter/source_helpers.rb
199
202
  - lib/docscribe/inline_rewriter/tag_sorter.rb
203
+ - lib/docscribe/lru_cache.rb
200
204
  - lib/docscribe/parsing.rb
201
205
  - lib/docscribe/plugin.rb
202
206
  - lib/docscribe/plugin/base/collector_plugin.rb
@@ -204,6 +208,7 @@ files:
204
208
  - lib/docscribe/plugin/context.rb
205
209
  - lib/docscribe/plugin/registry.rb
206
210
  - lib/docscribe/plugin/tag.rb
211
+ - lib/docscribe/server.rb
207
212
  - lib/docscribe/types/provider_chain.rb
208
213
  - lib/docscribe/types/rbs/collection_loader.rb
209
214
  - lib/docscribe/types/rbs/provider.rb
@@ -225,7 +230,7 @@ metadata:
225
230
  changelog_uri: https://github.com/unurgunite/docscribe/blob/master/CHANGELOG.md
226
231
  rubygems_mfa_required: 'true'
227
232
  post_install_message: |
228
- You installed docscribe 1.5.0. Your future self (and your team) thank you.
233
+ You installed docscribe 1.5.1. Your future self (and your team) thank you.
229
234
 
230
235
  $ docscribe --help
231
236