docscribe 1.3.2 → 1.4.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.
- checksums.yaml +4 -4
- data/README.md +38 -5
- data/lib/docscribe/cli/config_builder.rb +1 -1
- data/lib/docscribe/config/defaults.rb +1 -0
- data/lib/docscribe/config/rbs.rb +13 -0
- data/lib/docscribe/config/template.rb +1 -0
- data/lib/docscribe/inline_rewriter.rb +106 -1
- data/lib/docscribe/plugin/registry.rb +52 -9
- data/lib/docscribe/plugin.rb +22 -3
- data/lib/docscribe/types/rbs/provider.rb +35 -4
- data/lib/docscribe/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 50c74b921731749cbf32726e24e557e526e1f65966e704171a652d10cc4ce945
|
|
4
|
+
data.tar.gz: 2e254911cf9d81f5d5f7b5df29576c3c5c3c3f0433cfb387c0d22c1ce30eeb60
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 824133cf33505568edc84fe99bd51ced4451616552b2ba33e5584fcbd68bdd2ede0e4df365510a4e6be73ef9bf191a66e37746a5331e2ccb8abae2a80a3f69b4
|
|
7
|
+
data.tar.gz: 6662f828e5d324c226432df0e00359a36a97cd47dfeedefd4ead014752fbebe51b93e6cb693d6a342ca3d7e24683b74c189576792e558bf12e28bcc6365e2ed2
|
data/README.md
CHANGED
|
@@ -900,8 +900,9 @@ class DefineMethodPlugin < Docscribe::Plugin::Base::CollectorPlugin
|
|
|
900
900
|
end
|
|
901
901
|
end
|
|
902
902
|
|
|
903
|
-
|
|
904
|
-
Docscribe::Plugin::Registry.register(
|
|
903
|
+
# You can optionally set priority (default: 0). Higher number => higher priority.
|
|
904
|
+
Docscribe::Plugin::Registry.register(SincePlugin.new, priority: 10)
|
|
905
|
+
Docscribe::Plugin::Registry.register(DefineMethodPlugin.new, priority: 0)
|
|
905
906
|
```
|
|
906
907
|
|
|
907
908
|
**`docscribe.yml`**:
|
|
@@ -924,12 +925,34 @@ Docscribe::Plugin::Registry.register(
|
|
|
924
925
|
)
|
|
925
926
|
```
|
|
926
927
|
|
|
928
|
+
### Plugin priority
|
|
929
|
+
|
|
930
|
+
`Registry.register(plugin, priority: N)` accepts an optional integer priority (default: `0`).
|
|
931
|
+
Higher number means higher priority.
|
|
932
|
+
|
|
933
|
+
**CollectorPlugin priority (conflicts at the same source position):**
|
|
934
|
+
|
|
935
|
+
- If a plugin insertion and a standard *method* insertion share the same source position (
|
|
936
|
+
`anchor_node.loc.expression.begin_pos`), the standard insertion is dropped and the plugin insertion is kept.
|
|
937
|
+
- If multiple CollectorPlugins insert at the same source position, only insertions from the highest-priority plugin(s)
|
|
938
|
+
are kept (ties are kept).
|
|
939
|
+
- Multiple insertions from the winning plugin(s) at the same position are preserved (e.g. one `@!attribute` per column).
|
|
940
|
+
|
|
941
|
+
**TagPlugin priority:**
|
|
942
|
+
|
|
943
|
+
- TagPlugins run in descending priority order (higher priority runs earlier).
|
|
944
|
+
- Multiple TagPlugins may emit the same tag name (e.g. two `@since` tags) — duplicates in the same run are allowed.
|
|
945
|
+
|
|
946
|
+
This allows plugins like `ModelAttributes` to supply more accurate `@return`
|
|
947
|
+
types for ActiveRecord model methods, replacing the generic docs the standard
|
|
948
|
+
collector would have produced for the same `def`.
|
|
949
|
+
|
|
927
950
|
### Idempotency
|
|
928
951
|
|
|
929
952
|
Docscribe handles idempotency for plugins automatically.
|
|
930
953
|
|
|
931
|
-
**TagPlugin**:
|
|
932
|
-
|
|
954
|
+
**TagPlugin**: in safe merge mode, Docscribe will not add a plugin tag if the existing doc block already contains a tag
|
|
955
|
+
with that name. (Multiple TagPlugins can still emit the same tag name in a single run; duplicates are allowed.)
|
|
933
956
|
|
|
934
957
|
**CollectorPlugin**: idempotency depends on the selected strategy.
|
|
935
958
|
|
|
@@ -943,7 +966,17 @@ on aggressive runs.
|
|
|
943
966
|
|
|
944
967
|
### Plugin examples
|
|
945
968
|
|
|
946
|
-
Sample
|
|
969
|
+
Sample plugins available at [examples](examples/plugins):
|
|
970
|
+
|
|
971
|
+
- **`ApiTagPlugin`** (`tag_plugin/`): TagPlugin that appends `@api public` / `@api private`
|
|
972
|
+
based on method visibility.
|
|
973
|
+
- **`RailsAssociations`** (`collector_plugin/rails_associations/`): CollectorPlugin
|
|
974
|
+
that documents ActiveRecord `belongs_to`, `has_many`, etc.
|
|
975
|
+
- **`SchemaAttributes`** (`collector_plugin/schema_attributes/`): CollectorPlugin
|
|
976
|
+
that generates `@!attribute` blocks by reading `db/schema.rb`.
|
|
977
|
+
- **`ModelAttributes`** (`collector_plugin/model_attributes/`): CollectorPlugin
|
|
978
|
+
that generates accurate `@return` types for model methods using `db/schema.rb`
|
|
979
|
+
or `db/structure.sql`.
|
|
947
980
|
|
|
948
981
|
## Configuration
|
|
949
982
|
|
|
@@ -53,7 +53,7 @@ module Docscribe
|
|
|
53
53
|
require 'docscribe/types/rbs/collection_loader'
|
|
54
54
|
collection_path = Docscribe::Types::RBS::CollectionLoader.resolve
|
|
55
55
|
if collection_path
|
|
56
|
-
raw['rbs']['
|
|
56
|
+
raw['rbs']['collection_dirs'] = Array(raw['rbs']['collection_dirs']) + [collection_path]
|
|
57
57
|
else
|
|
58
58
|
warn 'Docscribe: rbs_collection.lock.yaml not found or collection not installed. ' \
|
|
59
59
|
'Run `bundle exec rbs collection install` first.'
|
data/lib/docscribe/config/rbs.rb
CHANGED
|
@@ -17,6 +17,7 @@ module Docscribe
|
|
|
17
17
|
require 'docscribe/types/rbs/provider'
|
|
18
18
|
Docscribe::Types::RBS::Provider.new(
|
|
19
19
|
sig_dirs: rbs_sig_dirs,
|
|
20
|
+
collection_dirs: rbs_collection_dirs,
|
|
20
21
|
collapse_generics: rbs_collapse_generics?
|
|
21
22
|
)
|
|
22
23
|
rescue LoadError
|
|
@@ -73,6 +74,18 @@ module Docscribe
|
|
|
73
74
|
Array(raw.dig('rbs', 'sig_dirs') || DEFAULT.dig('rbs', 'sig_dirs')).map(&:to_s)
|
|
74
75
|
end
|
|
75
76
|
|
|
77
|
+
# RBS collection directories (auto-discovered from rbs_collection.lock.yaml).
|
|
78
|
+
#
|
|
79
|
+
# Loaded separately from user sig_dirs so that collection-related
|
|
80
|
+
# RBS environment errors (e.g. duplicate declarations against core
|
|
81
|
+
# stdlib types) do not silence all RBS lookups.
|
|
82
|
+
#
|
|
83
|
+
# @private
|
|
84
|
+
# @return [Array<String>]
|
|
85
|
+
def rbs_collection_dirs
|
|
86
|
+
Array(raw.dig('rbs', 'collection_dirs')).map(&:to_s)
|
|
87
|
+
end
|
|
88
|
+
|
|
76
89
|
# Whether generic RBS types should be collapsed to simpler container names.
|
|
77
90
|
#
|
|
78
91
|
# Examples:
|
|
@@ -86,6 +86,7 @@ module Docscribe
|
|
|
86
86
|
# Use RBS signatures for better types (requires `gem "rbs"`)
|
|
87
87
|
enabled: false
|
|
88
88
|
sig_dirs: ["sig"]
|
|
89
|
+
collection_dirs: [] # auto-discovered from --rbs-collection
|
|
89
90
|
collapse_generics: false # Hash<Symbol, String> => Hash
|
|
90
91
|
collection: false # auto-discover from rbs_collection.lock.yaml
|
|
91
92
|
|
|
@@ -102,6 +102,7 @@ module Docscribe
|
|
|
102
102
|
all = method_insertions.map { |i| [:method, i] } +
|
|
103
103
|
attr_insertions.map { |i| [:attr, i] } +
|
|
104
104
|
plugin_insertions.map { |i| [:plugin, i] }
|
|
105
|
+
all = deduplicate_insertions(all)
|
|
105
106
|
rewriter = Parser::Source::TreeRewriter.new(buffer)
|
|
106
107
|
merge_inserts = Hash.new { |h, k| h[k] = [] }
|
|
107
108
|
changes = []
|
|
@@ -148,6 +149,110 @@ module Docscribe
|
|
|
148
149
|
|
|
149
150
|
private
|
|
150
151
|
|
|
152
|
+
# Deduplicate insertions by source position.
|
|
153
|
+
#
|
|
154
|
+
# Rules:
|
|
155
|
+
# 1. Plugin insertions override method insertions at the same position
|
|
156
|
+
# (CollectorPlugin knows more than the standard collector for that node).
|
|
157
|
+
# 2. If multiple CollectorPlugins target the same position, only insertions
|
|
158
|
+
# from the highest priority plugin(s) are kept (ties are kept).
|
|
159
|
+
# 3. Multiple plugin insertions at the same position are allowed
|
|
160
|
+
# (a single plugin may generate multiple doc blocks, e.g. one per column).
|
|
161
|
+
#
|
|
162
|
+
# @private
|
|
163
|
+
# @param [Array<Array(Symbol,Object)>] insertions tagged insertion list
|
|
164
|
+
# @return [Array<Array(Symbol,Object)>]
|
|
165
|
+
def deduplicate_insertions(insertions)
|
|
166
|
+
groups = {}
|
|
167
|
+
|
|
168
|
+
insertions.each do |item|
|
|
169
|
+
kind, ins = item
|
|
170
|
+
pos = plugin_insertion_pos(kind, ins)
|
|
171
|
+
(groups[pos] ||= []) << item
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
result = []
|
|
175
|
+
|
|
176
|
+
groups.each do |pos, items|
|
|
177
|
+
plugin_items = items.select { |k, _| k == :plugin }
|
|
178
|
+
|
|
179
|
+
# No plugins at this position -> keep as-is
|
|
180
|
+
if plugin_items.empty?
|
|
181
|
+
result.concat(items)
|
|
182
|
+
next
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Rule 1: plugin overrides method insertion at the same position
|
|
186
|
+
items = items.reject { |k, _| k == :method }
|
|
187
|
+
|
|
188
|
+
# Rule 2: keep only highest-priority plugin insertions
|
|
189
|
+
max_prio = plugin_items.map { |_k, ins| plugin_insertion_priority(ins) }.max || 0
|
|
190
|
+
|
|
191
|
+
items = items.reject do |k, ins|
|
|
192
|
+
k == :plugin && plugin_insertion_priority(ins) < max_prio
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Warn on ties between different plugins at the winning priority
|
|
196
|
+
if Docscribe::Plugin.debug?
|
|
197
|
+
kept_plugin_labels =
|
|
198
|
+
items
|
|
199
|
+
.select { |k, _| k == :plugin }
|
|
200
|
+
.map { |_k, ins| plugin_insertion_label(ins) }
|
|
201
|
+
.uniq
|
|
202
|
+
|
|
203
|
+
if kept_plugin_labels.size > 1
|
|
204
|
+
line = plugin_insertion_line(plugin_items.first[1])
|
|
205
|
+
loc = +"pos=#{pos}"
|
|
206
|
+
loc << " line=#{line}" if line
|
|
207
|
+
|
|
208
|
+
warn "Docscribe: CollectorPlugin conflict at #{loc} (priority=#{max_prio}): " \
|
|
209
|
+
"#{kept_plugin_labels.join(', ')} — keeping all. Set explicit priority to resolve."
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
result.concat(items)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
result
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# @private
|
|
220
|
+
# @param [Hash] insertion
|
|
221
|
+
# @raise [StandardError]
|
|
222
|
+
# @return [Integer]
|
|
223
|
+
def plugin_insertion_priority(insertion)
|
|
224
|
+
return 0 unless insertion.is_a?(Hash)
|
|
225
|
+
|
|
226
|
+
Integer(insertion[:__docscribe_priority] || 0)
|
|
227
|
+
rescue StandardError
|
|
228
|
+
0
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# @private
|
|
232
|
+
# @param [Hash] insertion
|
|
233
|
+
# @raise [StandardError]
|
|
234
|
+
# @return [String]
|
|
235
|
+
def plugin_insertion_label(insertion)
|
|
236
|
+
return 'unknown' unless insertion.is_a?(Hash)
|
|
237
|
+
|
|
238
|
+
label = insertion[:__docscribe_plugin_class].to_s
|
|
239
|
+
label.empty? ? 'unknown' : label
|
|
240
|
+
rescue StandardError
|
|
241
|
+
'unknown'
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# @private
|
|
245
|
+
# @param [Hash] insertion
|
|
246
|
+
# @raise [StandardError]
|
|
247
|
+
# @return [Integer, nil]
|
|
248
|
+
def plugin_insertion_line(insertion)
|
|
249
|
+
return nil unless insertion.is_a?(Hash)
|
|
250
|
+
|
|
251
|
+
insertion[:anchor_node]&.loc&.expression&.line
|
|
252
|
+
rescue StandardError
|
|
253
|
+
nil
|
|
254
|
+
end
|
|
255
|
+
|
|
151
256
|
# Resolve the source begin_pos for sorting, handling both Struct-based
|
|
152
257
|
# insertions (method/attr) and Hash-based insertions (plugin).
|
|
153
258
|
#
|
|
@@ -239,7 +344,7 @@ module Docscribe
|
|
|
239
344
|
Parser::Source::Range.new(buffer, start_pos, bol_pos)
|
|
240
345
|
end
|
|
241
346
|
|
|
242
|
-
#
|
|
347
|
+
# Normalize indentation of a plugin-generated doc block.
|
|
243
348
|
#
|
|
244
349
|
# Plugins produce doc strings without knowledge of the surrounding
|
|
245
350
|
# indentation. We strip leading whitespace from each non-empty line
|
|
@@ -11,8 +11,22 @@ module Docscribe
|
|
|
11
11
|
# Thread safety: registration is expected to happen before any parallel
|
|
12
12
|
# rewriting begins.
|
|
13
13
|
module Registry
|
|
14
|
-
|
|
15
|
-
@
|
|
14
|
+
# @!attribute [rw] plugin
|
|
15
|
+
# @return [Object]
|
|
16
|
+
# @param [Object] value
|
|
17
|
+
#
|
|
18
|
+
# @!attribute [rw] priority
|
|
19
|
+
# @return [Object]
|
|
20
|
+
# @param [Object] value
|
|
21
|
+
#
|
|
22
|
+
# @!attribute [rw] order
|
|
23
|
+
# @return [Object]
|
|
24
|
+
# @param [Object] value
|
|
25
|
+
Entry = Struct.new(:plugin, :priority, :order, keyword_init: true)
|
|
26
|
+
|
|
27
|
+
@tag_entries = []
|
|
28
|
+
@collector_entries = []
|
|
29
|
+
@order_seq = 0
|
|
16
30
|
|
|
17
31
|
module_function
|
|
18
32
|
|
|
@@ -26,13 +40,25 @@ module Docscribe
|
|
|
26
40
|
#
|
|
27
41
|
# @note module_function: when included, also defines #register (instance visibility: private)
|
|
28
42
|
# @param [Object] plugin plugin instance
|
|
43
|
+
# @param [Integer] priority plugin priority (higher wins for conflicts)
|
|
29
44
|
# @raise [ArgumentError] if plugin type cannot be determined
|
|
45
|
+
# @raise [StandardError]
|
|
30
46
|
# @return [void]
|
|
31
|
-
def register(plugin)
|
|
47
|
+
def register(plugin, priority: 0)
|
|
48
|
+
prio =
|
|
49
|
+
begin
|
|
50
|
+
Integer(priority)
|
|
51
|
+
rescue StandardError
|
|
52
|
+
raise ArgumentError, "priority must be an Integer-like value, got: #{priority.inspect}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
@order_seq += 1
|
|
56
|
+
entry = Entry.new(plugin: plugin, priority: prio, order: @order_seq)
|
|
57
|
+
|
|
32
58
|
if plugin.is_a?(Base::CollectorPlugin) || plugin.respond_to?(:collect)
|
|
33
|
-
@
|
|
59
|
+
@collector_entries << entry
|
|
34
60
|
elsif plugin.is_a?(Base::TagPlugin) || plugin.respond_to?(:call)
|
|
35
|
-
@
|
|
61
|
+
@tag_entries << entry
|
|
36
62
|
else
|
|
37
63
|
raise ArgumentError, 'Plugin must respond to #call (TagPlugin) or #collect (CollectorPlugin)'
|
|
38
64
|
end
|
|
@@ -43,7 +69,7 @@ module Docscribe
|
|
|
43
69
|
# @note module_function: when included, also defines #tag_plugins (instance visibility: private)
|
|
44
70
|
# @return [Array<#call>]
|
|
45
71
|
def tag_plugins
|
|
46
|
-
@
|
|
72
|
+
@tag_entries.map(&:plugin)
|
|
47
73
|
end
|
|
48
74
|
|
|
49
75
|
# All registered collector plugins in registration order.
|
|
@@ -51,7 +77,23 @@ module Docscribe
|
|
|
51
77
|
# @note module_function: when included, also defines #collector_plugins (instance visibility: private)
|
|
52
78
|
# @return [Array<#collect>]
|
|
53
79
|
def collector_plugins
|
|
54
|
-
@
|
|
80
|
+
@collector_entries.map(&:plugin)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# All registered tag plugin entries (plugin + priority metadata).
|
|
84
|
+
#
|
|
85
|
+
# @note module_function: when included, also defines #tag_entries (instance visibility: private)
|
|
86
|
+
# @return [Array<Entry>]
|
|
87
|
+
def tag_entries
|
|
88
|
+
@tag_entries.dup
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# All registered collector plugin entries (plugin + priority metadata).
|
|
92
|
+
#
|
|
93
|
+
# @note module_function: when included, also defines #collector_entries (instance visibility: private)
|
|
94
|
+
# @return [Array<Entry>]
|
|
95
|
+
def collector_entries
|
|
96
|
+
@collector_entries.dup
|
|
55
97
|
end
|
|
56
98
|
|
|
57
99
|
# Remove all registered plugins.
|
|
@@ -61,8 +103,9 @@ module Docscribe
|
|
|
61
103
|
# @note module_function: when included, also defines #clear! (instance visibility: private)
|
|
62
104
|
# @return [void]
|
|
63
105
|
def clear!
|
|
64
|
-
@
|
|
65
|
-
@
|
|
106
|
+
@tag_entries.clear
|
|
107
|
+
@collector_entries.clear
|
|
108
|
+
@order_seq = 0
|
|
66
109
|
end
|
|
67
110
|
end
|
|
68
111
|
end
|
data/lib/docscribe/plugin.rb
CHANGED
|
@@ -27,7 +27,13 @@ module Docscribe
|
|
|
27
27
|
# @raise [StandardError]
|
|
28
28
|
# @return [Array<Docscribe::Plugin::Tag>]
|
|
29
29
|
def self.run_tag_plugins(context)
|
|
30
|
-
Registry.
|
|
30
|
+
Registry.tag_entries
|
|
31
|
+
# Higher number => higher priority (run earlier).
|
|
32
|
+
# This matters when multiple TagPlugins emit the same tag name
|
|
33
|
+
# and Docscribe deduplicates tags by name.
|
|
34
|
+
.sort_by { |entry| [-entry.priority, entry.order] }
|
|
35
|
+
.flat_map do |entry|
|
|
36
|
+
plugin = entry.plugin
|
|
31
37
|
plugin.call(context)
|
|
32
38
|
rescue StandardError => e
|
|
33
39
|
warn "Docscribe: TagPlugin #{plugin.class} raised #{e.class}: #{e.message}" if debug?
|
|
@@ -42,8 +48,21 @@ module Docscribe
|
|
|
42
48
|
# @raise [StandardError]
|
|
43
49
|
# @return [Array<Hash>]
|
|
44
50
|
def self.run_collector_plugins(ast, buffer)
|
|
45
|
-
Registry.
|
|
46
|
-
plugin.
|
|
51
|
+
Registry.collector_entries.flat_map do |entry|
|
|
52
|
+
plugin = entry.plugin
|
|
53
|
+
|
|
54
|
+
Array(plugin.collect(ast, buffer)).map do |insertion|
|
|
55
|
+
unless insertion.is_a?(Hash)
|
|
56
|
+
warn "Docscribe: CollectorPlugin #{plugin.class} returned #{insertion.class}, expected Hash" if debug?
|
|
57
|
+
next nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
insertion.merge(
|
|
61
|
+
__docscribe_priority: entry.priority,
|
|
62
|
+
__docscribe_plugin_class: plugin.class.name,
|
|
63
|
+
__docscribe_plugin_order: entry.order
|
|
64
|
+
)
|
|
65
|
+
end.compact
|
|
47
66
|
rescue StandardError => e
|
|
48
67
|
warn "Docscribe: CollectorPlugin #{plugin.class} raised #{e.class}: #{e.message}" if debug?
|
|
49
68
|
[]
|
|
@@ -15,16 +15,21 @@ module Docscribe
|
|
|
15
15
|
# the pipeline can stay independent of the underlying signature source.
|
|
16
16
|
class Provider
|
|
17
17
|
# @param [Array<String>] sig_dirs directories containing `.rbs` files
|
|
18
|
+
# @param [Array<String>] collection_dirs RBS collection directories
|
|
19
|
+
# (loaded separately; on error they are silently dropped and only
|
|
20
|
+
# user sig_dirs are used)
|
|
18
21
|
# @param [Boolean] collapse_generics whether generic container types
|
|
19
22
|
# should be simplified during formatting
|
|
20
23
|
# @return [Object]
|
|
21
|
-
def initialize(sig_dirs:, collapse_generics: false)
|
|
24
|
+
def initialize(sig_dirs:, collection_dirs: [], collapse_generics: false)
|
|
22
25
|
require 'rbs'
|
|
23
26
|
@sig_dirs = Array(sig_dirs).map(&:to_s)
|
|
27
|
+
@collection_dirs = Array(collection_dirs).map(&:to_s)
|
|
24
28
|
@collapse_generics = !!collapse_generics
|
|
25
29
|
@env = nil
|
|
26
30
|
@builder = nil
|
|
27
31
|
@warned = false
|
|
32
|
+
@collection_dropped = false
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
# Look up a normalized method signature from loaded RBS definitions.
|
|
@@ -64,22 +69,48 @@ module Docscribe
|
|
|
64
69
|
|
|
65
70
|
# Lazily load and resolve the RBS environment.
|
|
66
71
|
#
|
|
72
|
+
# Tries to load collection dirs together with user sig_dirs.
|
|
73
|
+
# If the combined environment raises a load error (e.g. duplicate
|
|
74
|
+
# declarations between collection and core stdlib types), collection
|
|
75
|
+
# dirs are dropped and only user sig_dirs are used.
|
|
76
|
+
#
|
|
67
77
|
# @private
|
|
78
|
+
# @raise [::RBS::BaseError]
|
|
79
|
+
# @raise [StandardError]
|
|
68
80
|
# @return [void]
|
|
69
81
|
def load_env!
|
|
70
82
|
return if @env && @builder
|
|
71
83
|
|
|
84
|
+
@env = build_env(@sig_dirs + @collection_dirs)
|
|
85
|
+
rescue ::RBS::BaseError => e
|
|
86
|
+
raise unless @collection_dirs.any? && !@collection_dropped
|
|
87
|
+
|
|
88
|
+
@collection_dropped = true
|
|
89
|
+
if ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
|
|
90
|
+
warn "Docscribe: RBS collection error (#{e.class}), dropping collection dirs. " \
|
|
91
|
+
'Set DOCSCRIBE_RBS_DEBUG=1 for details.'
|
|
92
|
+
end
|
|
93
|
+
@env = build_env(@sig_dirs)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Build an RBS environment from the given directories.
|
|
97
|
+
#
|
|
98
|
+
# @private
|
|
99
|
+
# @param [Array<String>] dirs
|
|
100
|
+
# @return [::RBS::Environment]
|
|
101
|
+
def build_env(dirs)
|
|
72
102
|
loader = ::RBS::EnvironmentLoader.new
|
|
73
103
|
# Load core types transitively
|
|
74
104
|
loader.add(library: 'rbs')
|
|
75
105
|
|
|
76
|
-
|
|
106
|
+
dirs.each do |dir|
|
|
77
107
|
path = Pathname(dir)
|
|
78
108
|
loader.add(path: path) if path.directory?
|
|
79
109
|
end
|
|
80
110
|
|
|
81
|
-
|
|
82
|
-
@builder = ::RBS::DefinitionBuilder.new(env:
|
|
111
|
+
env = ::RBS::Environment.from_loader(loader).resolve_type_names
|
|
112
|
+
@builder = ::RBS::DefinitionBuilder.new(env: env)
|
|
113
|
+
env
|
|
83
114
|
end
|
|
84
115
|
|
|
85
116
|
# Build the appropriate instance or singleton definition for a container.
|
data/lib/docscribe/version.rb
CHANGED