docscribe 1.3.0 → 1.3.2
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/lib/docscribe/cli/config_builder.rb +1 -1
- data/lib/docscribe/cli/run.rb +35 -6
- data/lib/docscribe/config/defaults.rb +5 -2
- data/lib/docscribe/config/rbs.rb +38 -1
- data/lib/docscribe/config/template.rb +54 -147
- data/lib/docscribe/infer/returns.rb +103 -25
- data/lib/docscribe/inline_rewriter/doc_block.rb +10 -1
- data/lib/docscribe/inline_rewriter/doc_builder.rb +66 -9
- data/lib/docscribe/inline_rewriter.rb +31 -26
- data/lib/docscribe/plugin/base/collector_plugin.rb +0 -2
- data/lib/docscribe/types/rbs/provider.rb +18 -1
- data/lib/docscribe/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 765dd81d49b3cbf47c90f83f9e533a367da6590f84b15ca7e49de66c6140b5e1
|
|
4
|
+
data.tar.gz: b7c0607de2fb6e2344be24d4da58c1e03ab33755175783e1e6de8c934a8f2cdc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f30b33860317c5b9914e6b6c633df75c35f11883d7524c3b832365431a5f47760eaaeb4daab3b20f358bad8cb088015b173d6848bf65b3d7cbba18a69fda5154
|
|
7
|
+
data.tar.gz: 66ac534ba8452880ee778ae1bf72ce571e9ea4bba481e5595172314df1f809eb62db87ec8b77cd4efb8c8cd37c85dd0c937b7fa8c263938ab46734ae03f5acda
|
|
@@ -44,7 +44,7 @@ module Docscribe
|
|
|
44
44
|
raw['filter']['files']['include'] = Array(raw['filter']['files']['include']) + options[:include_file]
|
|
45
45
|
raw['filter']['files']['exclude'] = Array(raw['filter']['files']['exclude']) + options[:exclude_file]
|
|
46
46
|
|
|
47
|
-
if options[:rbs] || options[:sig_dirs].any?
|
|
47
|
+
if options[:rbs] || options[:rbs_collection] || options[:sig_dirs].any?
|
|
48
48
|
raw['rbs'] ||= {}
|
|
49
49
|
raw['rbs']['enabled'] = true
|
|
50
50
|
raw['rbs']['sig_dirs'] = Array(raw['rbs']['sig_dirs']) + options[:sig_dirs] if options[:sig_dirs].any?
|
data/lib/docscribe/cli/run.rb
CHANGED
|
@@ -148,7 +148,9 @@ module Docscribe
|
|
|
148
148
|
fail_paths: [],
|
|
149
149
|
fail_changes: {},
|
|
150
150
|
error_paths: [],
|
|
151
|
-
error_messages: {}
|
|
151
|
+
error_messages: {},
|
|
152
|
+
type_mismatch_paths: [],
|
|
153
|
+
type_mismatch_changes: {}
|
|
152
154
|
}
|
|
153
155
|
end
|
|
154
156
|
|
|
@@ -278,9 +280,18 @@ module Docscribe
|
|
|
278
280
|
# @param [Hash] state shared processing state
|
|
279
281
|
# @return [void]
|
|
280
282
|
def handle_check_result(path, src:, out:, file_changes:, display_path:, options:, state:)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
283
|
+
type_mismatches = file_changes.select { |c| %i[updated_param updated_return].include?(c[:type]) }
|
|
284
|
+
has_real_changes = file_changes.any? { |c| !%i[updated_param updated_return].include?(c[:type]) }
|
|
285
|
+
|
|
286
|
+
if out == src && !has_real_changes
|
|
287
|
+
if type_mismatches.any?
|
|
288
|
+
state[:type_mismatch_paths] << path
|
|
289
|
+
state[:type_mismatch_changes][path] = type_mismatches
|
|
290
|
+
options[:verbose] ? puts("MT #{display_path}") : print('M')
|
|
291
|
+
else
|
|
292
|
+
state[:checked_ok] += 1
|
|
293
|
+
options[:verbose] ? puts("OK #{display_path}") : print('.')
|
|
294
|
+
end
|
|
284
295
|
return
|
|
285
296
|
end
|
|
286
297
|
|
|
@@ -350,13 +361,22 @@ module Docscribe
|
|
|
350
361
|
puts
|
|
351
362
|
|
|
352
363
|
checked_error = state[:error_paths].size
|
|
364
|
+
type_mismatch_count = state[:type_mismatch_paths].size
|
|
353
365
|
|
|
354
|
-
if state[:checked_fail].zero? && checked_error.zero?
|
|
366
|
+
if state[:checked_fail].zero? && checked_error.zero? && type_mismatch_count.zero?
|
|
355
367
|
puts "Docscribe: OK (#{state[:checked_ok]} files checked)"
|
|
356
368
|
return
|
|
357
369
|
end
|
|
358
370
|
|
|
359
|
-
|
|
371
|
+
if state[:checked_fail].zero? && checked_error.zero?
|
|
372
|
+
puts "Docscribe: OK (#{state[:checked_ok]} files checked, #{type_mismatch_count} with type mismatches)"
|
|
373
|
+
else
|
|
374
|
+
parts = ["#{state[:checked_fail]} need updates"]
|
|
375
|
+
parts << "#{type_mismatch_count} type mismatches" if type_mismatch_count.positive?
|
|
376
|
+
parts << "#{checked_error} errors"
|
|
377
|
+
parts << "#{state[:checked_ok]} ok"
|
|
378
|
+
puts "Docscribe: FAILED (#{parts.join(', ')})"
|
|
379
|
+
end
|
|
360
380
|
|
|
361
381
|
state[:fail_paths].each do |p|
|
|
362
382
|
warn "Would update docs: #{p}"
|
|
@@ -367,6 +387,15 @@ module Docscribe
|
|
|
367
387
|
end
|
|
368
388
|
end
|
|
369
389
|
|
|
390
|
+
if options[:verbose] || options[:explain]
|
|
391
|
+
state[:type_mismatch_paths].each do |p|
|
|
392
|
+
warn "Type mismatches: #{p}"
|
|
393
|
+
Array(state[:type_mismatch_changes][p]).each do |change|
|
|
394
|
+
warn " - #{format_change_reason(change)}"
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
370
399
|
state[:error_paths].each do |p|
|
|
371
400
|
warn "Error processing: #{p}"
|
|
372
401
|
warn " #{state[:error_messages][p]}" if state[:error_messages][p]
|
|
@@ -14,7 +14,9 @@ module Docscribe
|
|
|
14
14
|
# - optional Sorbet integration
|
|
15
15
|
DEFAULT = {
|
|
16
16
|
'emit' => {
|
|
17
|
-
'header' =>
|
|
17
|
+
'header' => false,
|
|
18
|
+
'include_default_message' => true,
|
|
19
|
+
'include_param_documentation' => true,
|
|
18
20
|
'param_tags' => true,
|
|
19
21
|
'return_tag' => true,
|
|
20
22
|
'visibility_tags' => true,
|
|
@@ -53,11 +55,12 @@ module Docscribe
|
|
|
53
55
|
'exclude' => [],
|
|
54
56
|
'files' => {
|
|
55
57
|
'include' => [],
|
|
56
|
-
'exclude' => []
|
|
58
|
+
'exclude' => ['spec']
|
|
57
59
|
}
|
|
58
60
|
},
|
|
59
61
|
'rbs' => {
|
|
60
62
|
'enabled' => false,
|
|
63
|
+
'collection' => false,
|
|
61
64
|
'sig_dirs' => ['sig'],
|
|
62
65
|
'collapse_generics' => false
|
|
63
66
|
},
|
data/lib/docscribe/config/rbs.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Docscribe
|
|
|
11
11
|
# @return [Docscribe::Types::RBS::Provider, nil]
|
|
12
12
|
def rbs_provider
|
|
13
13
|
return nil unless rbs_enabled?
|
|
14
|
+
return nil unless ruby_supports_rbs?
|
|
14
15
|
|
|
15
16
|
@rbs_provider ||= begin
|
|
16
17
|
require 'docscribe/types/rbs/provider'
|
|
@@ -30,8 +31,43 @@ module Docscribe
|
|
|
30
31
|
fetch_bool(%w[rbs enabled], false)
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
# Method documentation.
|
|
35
|
+
#
|
|
36
|
+
# @raise [LoadError]
|
|
37
|
+
# @return [Object]
|
|
38
|
+
def core_rbs_provider
|
|
39
|
+
return nil unless ruby_supports_rbs?
|
|
40
|
+
|
|
41
|
+
@core_rbs_provider ||= begin
|
|
42
|
+
require 'docscribe/types/rbs/provider'
|
|
43
|
+
Docscribe::Types::RBS::Provider.new(
|
|
44
|
+
sig_dirs: [],
|
|
45
|
+
collapse_generics: false
|
|
46
|
+
)
|
|
47
|
+
rescue LoadError
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
# Method documentation.
|
|
55
|
+
#
|
|
56
|
+
# @private
|
|
57
|
+
# @return [Boolean]
|
|
58
|
+
def ruby_supports_rbs?
|
|
59
|
+
return true if RUBY_VERSION >= '3.0'
|
|
60
|
+
|
|
61
|
+
@rbs_warning_emitted ||= begin
|
|
62
|
+
warn 'Docscribe: RBS requires Ruby 3.0+. Falling back to inference.'
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
|
|
33
68
|
# Signature directories used by the RBS provider.
|
|
34
69
|
#
|
|
70
|
+
# @private
|
|
35
71
|
# @return [Array<String>]
|
|
36
72
|
def rbs_sig_dirs
|
|
37
73
|
Array(raw.dig('rbs', 'sig_dirs') || DEFAULT.dig('rbs', 'sig_dirs')).map(&:to_s)
|
|
@@ -43,7 +79,8 @@ module Docscribe
|
|
|
43
79
|
# - `Hash<Symbol, String>` => `Hash`
|
|
44
80
|
# - `Array<Integer>` => `Array`
|
|
45
81
|
#
|
|
46
|
-
# @
|
|
82
|
+
# @private
|
|
83
|
+
# @return [Object]
|
|
47
84
|
def rbs_collapse_generics?
|
|
48
85
|
fetch_bool(%w[rbs collapse_generics], false)
|
|
49
86
|
end
|
|
@@ -14,187 +14,94 @@ module Docscribe
|
|
|
14
14
|
---
|
|
15
15
|
# Docscribe configuration file
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
# bundle exec docscribe lib
|
|
19
|
-
#
|
|
20
|
-
# Apply safe doc updates:
|
|
21
|
-
# bundle exec docscribe -a lib
|
|
22
|
-
#
|
|
23
|
-
# Apply aggressive doc updates (rebuild existing doc blocks):
|
|
24
|
-
# bundle exec docscribe -A lib
|
|
17
|
+
# Docscribe works without this file — create it only for customization.
|
|
25
18
|
#
|
|
19
|
+
# Quick start:
|
|
20
|
+
# bundle exec docscribe lib # check what would change
|
|
21
|
+
# bundle exec docscribe -a lib # apply safe updates
|
|
22
|
+
# bundle exec docscribe -A lib # rebuild all doc blocks
|
|
26
23
|
|
|
27
24
|
emit:
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
include_param_documentation: true
|
|
40
|
-
|
|
41
|
-
# Emit @param tags.
|
|
42
|
-
param_tags: true
|
|
43
|
-
|
|
44
|
-
# Emit @return tag (can be overridden per scope/visibility under methods:).
|
|
45
|
-
return_tag: true
|
|
46
|
-
|
|
47
|
-
# Emit @private / @protected tags based on Ruby visibility context.
|
|
48
|
-
visibility_tags: true
|
|
49
|
-
|
|
50
|
-
# Emit @raise tags inferred from rescue clauses / raise/fail calls.
|
|
51
|
-
raise_tags: true
|
|
52
|
-
|
|
53
|
-
# Emit conditional rescue return tags:
|
|
54
|
-
#
|
|
55
|
-
# @return [String] if FooError, BarError
|
|
56
|
-
rescue_conditional_returns: true
|
|
57
|
-
|
|
58
|
-
# Generate @!attribute docs for attr_reader/attr_writer/attr_accessor.
|
|
59
|
-
attributes: false
|
|
25
|
+
# What to include in generated documentation
|
|
26
|
+
header: false # +MyClass#foo+ -> ReturnType
|
|
27
|
+
param_tags: true # @param tags
|
|
28
|
+
return_tag: true # @return tag
|
|
29
|
+
visibility_tags: true # @private / @protected
|
|
30
|
+
raise_tags: true # @raise tags
|
|
31
|
+
rescue_conditional_returns: true # @return [Type] if Error
|
|
32
|
+
attributes: false # @!attribute for attr_*
|
|
33
|
+
|
|
34
|
+
# Placeholder text for generated docs
|
|
35
|
+
include_default_message: true # "Method documentation."
|
|
36
|
+
include_param_documentation: true # "Param documentation."
|
|
60
37
|
|
|
61
38
|
doc:
|
|
62
|
-
# Default text
|
|
39
|
+
# Default text and formatting
|
|
63
40
|
default_message: "Method documentation."
|
|
64
|
-
|
|
65
|
-
# Default text appended to generated @param tags.
|
|
66
41
|
param_documentation: "Param documentation."
|
|
42
|
+
param_tag_style: "type_name" # "type_name" or "name_type"
|
|
43
|
+
sort_tags: true
|
|
44
|
+
tag_order: ["todo", "note", "api", "private", "protected", "param", "option", "yieldparam", "raise", "return"]
|
|
67
45
|
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
|
|
46
|
+
inference:
|
|
47
|
+
# Type inference behavior
|
|
48
|
+
fallback_type: "Object" # when uncertain
|
|
49
|
+
nil_as_optional: true # String | nil => String?
|
|
50
|
+
treat_options_keyword_as_hash: true # options: keyword => Hash
|
|
72
51
|
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
filter:
|
|
53
|
+
# Which methods and files to process
|
|
54
|
+
# Method format: "Container#method" (instance) or "Container.method" (class)
|
|
55
|
+
# Supports globs ("*#initialize") and regex ("/^MyApp::.*$/")
|
|
56
|
+
include: []
|
|
57
|
+
exclude: []
|
|
58
|
+
visibilities: ["public", "protected", "private"]
|
|
59
|
+
scopes: ["instance", "class"]
|
|
75
60
|
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
files:
|
|
62
|
+
# File paths relative to project root (globs or /regex/)
|
|
63
|
+
include: []
|
|
64
|
+
exclude: ["spec"]
|
|
78
65
|
|
|
79
66
|
methods:
|
|
80
|
-
#
|
|
67
|
+
# Override defaults per scope and visibility.
|
|
68
|
+
# Empty {} means "use values from `doc` section".
|
|
81
69
|
#
|
|
82
70
|
# Example:
|
|
83
|
-
# methods:
|
|
84
71
|
# instance:
|
|
85
72
|
# public:
|
|
86
73
|
# default_message: "Public API."
|
|
87
|
-
#
|
|
74
|
+
# private:
|
|
75
|
+
# return_tag: false
|
|
88
76
|
instance:
|
|
89
77
|
public: {}
|
|
90
78
|
protected: {}
|
|
91
79
|
private: {}
|
|
92
|
-
|
|
93
80
|
class:
|
|
94
81
|
public: {}
|
|
95
82
|
protected: {}
|
|
96
83
|
private: {}
|
|
97
84
|
|
|
98
|
-
inference:
|
|
99
|
-
# Type used when inference is uncertain.
|
|
100
|
-
fallback_type: "Object"
|
|
101
|
-
|
|
102
|
-
# Whether nil unions become optional types (for example String | nil => String?).
|
|
103
|
-
nil_as_optional: true
|
|
104
|
-
|
|
105
|
-
# Special-case: treat keyword arg named options/options: as a Hash.
|
|
106
|
-
treat_options_keyword_as_hash: true
|
|
107
|
-
|
|
108
|
-
filter:
|
|
109
|
-
# Filter which methods Docscribe touches.
|
|
110
|
-
#
|
|
111
|
-
# Method id format:
|
|
112
|
-
# instance: "MyModule::MyClass#instance_method"
|
|
113
|
-
# class: "MyModule::MyClass.class_method"
|
|
114
|
-
#
|
|
115
|
-
# Patterns:
|
|
116
|
-
# - glob: "*#initialize", "MyApp::*#*"
|
|
117
|
-
# - regex: "/^MyApp::.*#(foo|bar)$/"
|
|
118
|
-
#
|
|
119
|
-
# Semantics:
|
|
120
|
-
# - scopes / visibilities act as allow-lists
|
|
121
|
-
# - exclude wins
|
|
122
|
-
# - if include is empty => include everything (subject to allow-lists)
|
|
123
|
-
visibilities: ["public", "protected", "private"]
|
|
124
|
-
scopes: ["instance", "class"]
|
|
125
|
-
include: []
|
|
126
|
-
exclude: []
|
|
127
|
-
|
|
128
|
-
files:
|
|
129
|
-
# Filter which files Docscribe processes (paths are matched relative
|
|
130
|
-
# to the project root).
|
|
131
|
-
#
|
|
132
|
-
# Tips:
|
|
133
|
-
# - Use directory shorthand to exclude a whole directory:
|
|
134
|
-
# exclude: ["spec"]
|
|
135
|
-
# - Or use globs:
|
|
136
|
-
# exclude: ["spec/**/*.rb", "vendor/**/*.rb"]
|
|
137
|
-
include: []
|
|
138
|
-
exclude: ["spec"]
|
|
139
|
-
|
|
140
|
-
plugins:
|
|
141
|
-
# Load custom plugins by path or gem name.
|
|
142
|
-
#
|
|
143
|
-
# Each entry is passed to `require`. Registration happens inside
|
|
144
|
-
# the required file via Docscribe::Plugin::Registry.register.
|
|
145
|
-
#
|
|
146
|
-
# Example:
|
|
147
|
-
# require:
|
|
148
|
-
# - ./docscribe_plugins
|
|
149
|
-
# - docscribe-rails-associations
|
|
150
|
-
require: []
|
|
151
|
-
|
|
152
85
|
rbs:
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
# CLI equivalent:
|
|
156
|
-
# bundle exec docscribe -a --rbs --sig-dir sig lib
|
|
157
|
-
#
|
|
158
|
-
# Under Bundler, you may need `gem "rbs"` in your Gemfile (or a
|
|
159
|
-
# Gemfile that includes it), otherwise `require "rbs"` may fail and
|
|
160
|
-
# Docscribe will fall back to inference.
|
|
86
|
+
# Use RBS signatures for better types (requires `gem "rbs"`)
|
|
161
87
|
enabled: false
|
|
162
|
-
|
|
163
|
-
# Signature directories (repeatable via --sig-dir).
|
|
164
88
|
sig_dirs: ["sig"]
|
|
165
|
-
|
|
166
|
-
#
|
|
167
|
-
# - Hash<Symbol, String> => Hash
|
|
168
|
-
# - Array<Integer> => Array
|
|
169
|
-
collapse_generics: false
|
|
170
|
-
# Auto-discover RBS collection from rbs_collection.lock.yaml.
|
|
171
|
-
# Equivalent to --rbs-collection CLI flag.
|
|
172
|
-
# Requires `bundle exec rbs collection install` to have been run.
|
|
173
|
-
#
|
|
174
|
-
collection: false
|
|
89
|
+
collapse_generics: false # Hash<Symbol, String> => Hash
|
|
90
|
+
collection: false # auto-discover from rbs_collection.lock.yaml
|
|
175
91
|
|
|
176
92
|
sorbet:
|
|
177
|
-
#
|
|
178
|
-
# RBI files to improve @param / @return types.
|
|
179
|
-
#
|
|
180
|
-
# CLI equivalent:
|
|
181
|
-
# bundle exec docscribe -a --sorbet --rbi-dir sorbet/rbi lib
|
|
182
|
-
#
|
|
183
|
-
# Sorbet resolution order is:
|
|
184
|
-
# 1. inline `sig` in the current source file
|
|
185
|
-
# 2. RBI files
|
|
186
|
-
# 3. RBS
|
|
187
|
-
# 4. AST inference
|
|
93
|
+
# Use Sorbet inline sigs and RBI files for better types
|
|
188
94
|
enabled: false
|
|
189
|
-
|
|
190
|
-
# RBI directories scanned recursively for `.rbi` files
|
|
191
|
-
# (repeatable via --rbi-dir).
|
|
192
95
|
rbi_dirs: ["sorbet/rbi", "rbi"]
|
|
193
|
-
|
|
194
|
-
# If true, simplify generic types:
|
|
195
|
-
# - Hash<Symbol, String> => Hash
|
|
196
|
-
# - Array<Integer> => Array
|
|
197
96
|
collapse_generics: false
|
|
97
|
+
|
|
98
|
+
plugins:
|
|
99
|
+
# Load custom plugins
|
|
100
|
+
# Example:
|
|
101
|
+
# require:
|
|
102
|
+
# - ./docscribe_plugins
|
|
103
|
+
# - docscribe-rails-associations
|
|
104
|
+
require: []
|
|
198
105
|
YAML
|
|
199
106
|
end
|
|
200
107
|
end
|
|
@@ -24,7 +24,9 @@ module Docscribe
|
|
|
24
24
|
return FALLBACK_TYPE unless root && %i[def defs].include?(root.type)
|
|
25
25
|
|
|
26
26
|
body = root.children.last
|
|
27
|
-
|
|
27
|
+
local_var_types = build_local_variable_types(body)
|
|
28
|
+
last_expr_type(body, fallback_type: FALLBACK_TYPE, nil_as_optional: true,
|
|
29
|
+
local_var_types: local_var_types) || FALLBACK_TYPE
|
|
28
30
|
rescue Parser::SyntaxError
|
|
29
31
|
FALLBACK_TYPE
|
|
30
32
|
end
|
|
@@ -43,7 +45,9 @@ module Docscribe
|
|
|
43
45
|
|
|
44
46
|
return FALLBACK_TYPE unless body
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
local_var_types = build_local_variable_types(body)
|
|
49
|
+
last_expr_type(body, fallback_type: FALLBACK_TYPE, nil_as_optional: true,
|
|
50
|
+
local_var_types: local_var_types) || FALLBACK_TYPE
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
# Return a structured return-type spec for a method node.
|
|
@@ -70,11 +74,16 @@ module Docscribe
|
|
|
70
74
|
spec = { normal: FALLBACK_TYPE, rescues: [] }
|
|
71
75
|
return spec unless body
|
|
72
76
|
|
|
77
|
+
local_var_types = build_local_variable_types(body)
|
|
78
|
+
|
|
73
79
|
if body.type == :rescue
|
|
74
80
|
main_body = body.children[0]
|
|
81
|
+
rescue_local_var_types = build_local_variable_types(body)
|
|
82
|
+
all_local_var_types = rescue_local_var_types || local_var_types
|
|
75
83
|
spec[:normal] =
|
|
76
84
|
last_expr_type(main_body, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
77
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
85
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
86
|
+
local_var_types: all_local_var_types) || FALLBACK_TYPE
|
|
78
87
|
|
|
79
88
|
body.children.each do |ch|
|
|
80
89
|
next unless ch.is_a?(Parser::AST::Node) && ch.type == :resbody
|
|
@@ -83,19 +92,50 @@ module Docscribe
|
|
|
83
92
|
exc_names = Raises.exception_names_from_rescue_list(exc_list)
|
|
84
93
|
rtype =
|
|
85
94
|
last_expr_type(rescue_body, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
86
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
95
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
96
|
+
local_var_types: all_local_var_types) ||
|
|
87
97
|
fallback_type
|
|
88
98
|
spec[:rescues] << [exc_names, rtype]
|
|
89
99
|
end
|
|
90
100
|
else
|
|
91
101
|
spec[:normal] =
|
|
92
102
|
last_expr_type(body, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
93
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
103
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
104
|
+
local_var_types: local_var_types) || FALLBACK_TYPE
|
|
94
105
|
end
|
|
95
106
|
|
|
96
107
|
spec
|
|
97
108
|
end
|
|
98
109
|
|
|
110
|
+
# Resolve a return type from core RBS for a method call.
|
|
111
|
+
#
|
|
112
|
+
# @note module_function: when included, also defines #resolve_rbs_return_type (instance visibility: private)
|
|
113
|
+
# @private
|
|
114
|
+
# @param [Object] node Param documentation.
|
|
115
|
+
# @return [String] FALLBACK_TYPE if lookup fails
|
|
116
|
+
def build_local_variable_types(node)
|
|
117
|
+
types = {}
|
|
118
|
+
ASTWalk.walk(node) do |n|
|
|
119
|
+
case n.type
|
|
120
|
+
when :lvasgn, :gvasgn, :ivasgn
|
|
121
|
+
name = n.children[0].to_s
|
|
122
|
+
value = n.children[1]
|
|
123
|
+
if value
|
|
124
|
+
inferred = Literals.type_from_literal(value, fallback_type: FALLBACK_TYPE)
|
|
125
|
+
types[name] = inferred if inferred && inferred != FALLBACK_TYPE
|
|
126
|
+
end
|
|
127
|
+
when :casgn
|
|
128
|
+
name = n.children[0].to_s
|
|
129
|
+
value = n.children[2]
|
|
130
|
+
if value
|
|
131
|
+
inferred = Literals.type_from_literal(value, fallback_type: FALLBACK_TYPE)
|
|
132
|
+
types[name] = inferred if inferred && inferred != FALLBACK_TYPE
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
types.empty? ? nil : types
|
|
137
|
+
end
|
|
138
|
+
|
|
99
139
|
# Infer the type of the last expression in a node.
|
|
100
140
|
#
|
|
101
141
|
# Supports:
|
|
@@ -112,30 +152,37 @@ module Docscribe
|
|
|
112
152
|
# @param [Boolean] nil_as_optional whether `nil` unions should be rendered as optional types
|
|
113
153
|
# @param [Object, nil] core_rbs_provider optional RBS provider for core type lookup
|
|
114
154
|
# @param [Hash, nil] param_types parameter name -> type map for lvar resolution
|
|
155
|
+
# @param [nil] local_var_types Param documentation.
|
|
115
156
|
# @return [String, nil]
|
|
116
|
-
def last_expr_type(node, fallback_type:, nil_as_optional:, core_rbs_provider: nil, param_types: nil
|
|
157
|
+
def last_expr_type(node, fallback_type:, nil_as_optional:, core_rbs_provider: nil, param_types: nil,
|
|
158
|
+
local_var_types: nil)
|
|
117
159
|
return nil unless node
|
|
118
160
|
|
|
119
161
|
case node.type
|
|
120
162
|
when :begin
|
|
121
163
|
last_expr_type(node.children.last, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
122
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
164
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
165
|
+
local_var_types: local_var_types)
|
|
123
166
|
|
|
124
167
|
when :if
|
|
125
168
|
t = last_expr_type(node.children[1], fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
126
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
169
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
170
|
+
local_var_types: local_var_types)
|
|
127
171
|
e = last_expr_type(node.children[2], fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
128
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
172
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
173
|
+
local_var_types: local_var_types)
|
|
129
174
|
unify_types(t, e, fallback_type: fallback_type, nil_as_optional: nil_as_optional)
|
|
130
175
|
|
|
131
176
|
when :case
|
|
132
177
|
branches = node.children[1..].compact.flat_map do |child|
|
|
133
178
|
if child.type == :when
|
|
134
179
|
last_expr_type(child.children.last, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
135
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
180
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
181
|
+
local_var_types: local_var_types)
|
|
136
182
|
else
|
|
137
183
|
last_expr_type(child, fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
138
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
184
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
185
|
+
local_var_types: local_var_types)
|
|
139
186
|
end
|
|
140
187
|
end.compact
|
|
141
188
|
|
|
@@ -150,6 +197,36 @@ module Docscribe
|
|
|
150
197
|
when :return
|
|
151
198
|
Literals.type_from_literal(node.children.first, fallback_type: fallback_type)
|
|
152
199
|
|
|
200
|
+
when :block
|
|
201
|
+
send_node = node.children[0]
|
|
202
|
+
if send_node&.type == :send
|
|
203
|
+
recv = send_node.children[0]
|
|
204
|
+
meth = send_node.children[1]
|
|
205
|
+
|
|
206
|
+
if core_rbs_provider && recv&.type == :lvar
|
|
207
|
+
lvar_name = recv.children.first
|
|
208
|
+
recv_type = nil
|
|
209
|
+
recv_type = local_var_types[lvar_name.to_s] if local_var_types && lvar_name
|
|
210
|
+
recv_type = param_types[lvar_name.to_s] if !recv_type && param_types && lvar_name
|
|
211
|
+
if recv_type
|
|
212
|
+
rbs_type = resolve_rbs_return_type(recv_type, meth, core_rbs_provider)
|
|
213
|
+
return rbs_type unless rbs_type == FALLBACK_TYPE
|
|
214
|
+
end
|
|
215
|
+
elsif core_rbs_provider && recv&.type == :send
|
|
216
|
+
inner_type = last_expr_type(recv, fallback_type: nil, nil_as_optional: false,
|
|
217
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
218
|
+
local_var_types: local_var_types)
|
|
219
|
+
if inner_type
|
|
220
|
+
rbs_type = resolve_rbs_return_type(inner_type, meth, core_rbs_provider)
|
|
221
|
+
return rbs_type unless rbs_type == FALLBACK_TYPE
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
last_expr_type(node.children[2], fallback_type: fallback_type, nil_as_optional: nil_as_optional,
|
|
227
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
228
|
+
local_var_types: local_var_types)
|
|
229
|
+
|
|
153
230
|
when :send
|
|
154
231
|
recv = node.children[0]
|
|
155
232
|
meth = node.children[1]
|
|
@@ -158,20 +235,22 @@ module Docscribe
|
|
|
158
235
|
if core_rbs_provider && recv&.type == :send
|
|
159
236
|
# Chained call: arg.to_i.positive?
|
|
160
237
|
inner_type = last_expr_type(recv, fallback_type: nil, nil_as_optional: false,
|
|
161
|
-
core_rbs_provider: core_rbs_provider, param_types: param_types
|
|
238
|
+
core_rbs_provider: core_rbs_provider, param_types: param_types,
|
|
239
|
+
local_var_types: local_var_types)
|
|
162
240
|
if inner_type
|
|
163
241
|
rbs_type = resolve_rbs_return_type(inner_type, meth, core_rbs_provider)
|
|
164
242
|
return rbs_type unless rbs_type == FALLBACK_TYPE
|
|
165
243
|
end
|
|
244
|
+
|
|
166
245
|
elsif core_rbs_provider && recv&.type == :lvar
|
|
167
|
-
# Direct call:
|
|
246
|
+
# Direct call on local variable: p1.positive? or admins.any?
|
|
168
247
|
lvar_name = recv.children.first
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
248
|
+
recv_type = nil
|
|
249
|
+
recv_type = local_var_types[lvar_name.to_s] if local_var_types && lvar_name
|
|
250
|
+
recv_type = param_types[lvar_name.to_s] if !recv_type && param_types && lvar_name
|
|
251
|
+
if recv_type
|
|
252
|
+
rbs_type = resolve_rbs_return_type(recv_type, meth, core_rbs_provider)
|
|
253
|
+
return rbs_type unless rbs_type == FALLBACK_TYPE
|
|
175
254
|
end
|
|
176
255
|
end
|
|
177
256
|
|
|
@@ -182,14 +261,13 @@ module Docscribe
|
|
|
182
261
|
end
|
|
183
262
|
end
|
|
184
263
|
|
|
185
|
-
#
|
|
264
|
+
# Method documentation.
|
|
186
265
|
#
|
|
187
266
|
# @note module_function: when included, also defines #resolve_rbs_return_type (instance visibility: private)
|
|
188
|
-
# @
|
|
189
|
-
# @param [
|
|
190
|
-
# @param [
|
|
191
|
-
# @
|
|
192
|
-
# @return [String] FALLBACK_TYPE if lookup fails
|
|
267
|
+
# @param [Object] container_type Param documentation.
|
|
268
|
+
# @param [Object] method_name Param documentation.
|
|
269
|
+
# @param [Object] core_rbs_provider Param documentation.
|
|
270
|
+
# @return [Object]
|
|
193
271
|
def resolve_rbs_return_type(container_type, method_name, core_rbs_provider)
|
|
194
272
|
return FALLBACK_TYPE unless core_rbs_provider
|
|
195
273
|
|
|
@@ -65,11 +65,20 @@ module Docscribe
|
|
|
65
65
|
# @param [Array<String>] missing_lines generated tag lines to add
|
|
66
66
|
# @param [Boolean] sort_tags whether sortable tags should be reordered
|
|
67
67
|
# @param [Array<String>] tag_order configured sortable tag order
|
|
68
|
+
# @param [Hash] filter_existing Param documentation.
|
|
68
69
|
# @return [Array<String>]
|
|
69
|
-
def merge(existing_lines, missing_lines:, sort_tags:, tag_order:)
|
|
70
|
+
def merge(existing_lines, missing_lines:, sort_tags:, tag_order:, filter_existing: {})
|
|
70
71
|
existing_entries = parse(existing_lines, tag_order: tag_order)
|
|
71
72
|
missing_entries = parse_generated(missing_lines, tag_order: tag_order)
|
|
72
73
|
|
|
74
|
+
filter_param_names = filter_existing[:param_names] || []
|
|
75
|
+
filter_return = !!filter_existing[:return]
|
|
76
|
+
|
|
77
|
+
existing_entries = existing_entries.reject do |e|
|
|
78
|
+
(e.kind == :tag && e.tag == 'param' && filter_param_names.include?(e.subject)) ||
|
|
79
|
+
(e.kind == :tag && e.tag == 'return' && filter_return)
|
|
80
|
+
end
|
|
81
|
+
|
|
73
82
|
entries = existing_entries + missing_entries
|
|
74
83
|
entries = sort(entries, tag_order: tag_order) if sort_tags
|
|
75
84
|
|
|
@@ -228,10 +228,11 @@ module Docscribe
|
|
|
228
228
|
# @param [Object, nil] signature_provider
|
|
229
229
|
# @param [nil] core_rbs_provider Param documentation.
|
|
230
230
|
# @param [nil] param_types Param documentation.
|
|
231
|
+
# @param [nil] strategy Param documentation.
|
|
231
232
|
# @raise [StandardError]
|
|
232
233
|
# @return [Hash]
|
|
233
234
|
def build_missing_merge_result(insertion, existing_lines:, config:, signature_provider: nil,
|
|
234
|
-
core_rbs_provider: nil, param_types: nil)
|
|
235
|
+
core_rbs_provider: nil, param_types: nil, strategy: nil)
|
|
235
236
|
node = insertion.node
|
|
236
237
|
name = SourceHelpers.node_name(node)
|
|
237
238
|
return { lines: [], reasons: [] } unless name
|
|
@@ -283,10 +284,22 @@ module Docscribe
|
|
|
283
284
|
|
|
284
285
|
all_params&.each do |pl|
|
|
285
286
|
pname = extract_param_name_from_param_line(pl)
|
|
286
|
-
next
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
next unless pname
|
|
288
|
+
|
|
289
|
+
if !info[:param_names].include?(pname)
|
|
290
|
+
lines << "#{pl}\n"
|
|
291
|
+
reasons << { type: :missing_param, message: "missing @param #{pname}", extra: { param: pname } }
|
|
292
|
+
elsif external_sig && info[:param_types][pname]
|
|
293
|
+
new_type = extract_param_type_from_param_line(pl)
|
|
294
|
+
if new_type && info[:param_types][pname] != new_type
|
|
295
|
+
lines << "#{pl}\n" unless strategy == :safe
|
|
296
|
+
reasons << {
|
|
297
|
+
type: :updated_param,
|
|
298
|
+
message: "updated @param #{pname} from #{info[:param_types][pname]} to #{new_type}",
|
|
299
|
+
extra: { param: pname }
|
|
300
|
+
}
|
|
301
|
+
end
|
|
302
|
+
end
|
|
290
303
|
end
|
|
291
304
|
end
|
|
292
305
|
|
|
@@ -301,9 +314,17 @@ module Docscribe
|
|
|
301
314
|
end
|
|
302
315
|
end
|
|
303
316
|
|
|
304
|
-
if config.emit_return_tag?(scope, visibility)
|
|
305
|
-
|
|
306
|
-
|
|
317
|
+
if config.emit_return_tag?(scope, visibility)
|
|
318
|
+
if !info[:has_return]
|
|
319
|
+
lines << "#{indent}# @return [#{normal_type}]\n"
|
|
320
|
+
reasons << { type: :missing_return, message: 'missing @return' }
|
|
321
|
+
elsif external_sig && info[:return_type] && info[:return_type] != normal_type
|
|
322
|
+
lines << "#{indent}# @return [#{normal_type}]\n" unless strategy == :safe
|
|
323
|
+
reasons << {
|
|
324
|
+
type: :updated_return,
|
|
325
|
+
message: "updated @return from #{info[:return_type]} to #{normal_type}"
|
|
326
|
+
}
|
|
327
|
+
end
|
|
307
328
|
end
|
|
308
329
|
|
|
309
330
|
if config.emit_rescue_conditional_returns? && !info[:has_return]
|
|
@@ -341,7 +362,9 @@ module Docscribe
|
|
|
341
362
|
# @return [Hash] parsed tag info
|
|
342
363
|
def parse_existing_doc_tags(lines)
|
|
343
364
|
param_names = {}
|
|
365
|
+
param_types = {}
|
|
344
366
|
has_return = false
|
|
367
|
+
return_type = nil
|
|
345
368
|
has_private = false
|
|
346
369
|
has_protected = false
|
|
347
370
|
has_module_function_note = false
|
|
@@ -354,9 +377,17 @@ module Docscribe
|
|
|
354
377
|
end
|
|
355
378
|
if (pname = extract_param_name_from_param_line(line))
|
|
356
379
|
param_names[pname] = true
|
|
380
|
+
if (type_match = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
|
|
381
|
+
param_types[pname] = type_match[1]
|
|
382
|
+
end
|
|
357
383
|
end
|
|
358
384
|
|
|
359
|
-
|
|
385
|
+
if line.match?(/^\s*#\s*@return\b/)
|
|
386
|
+
has_return = true
|
|
387
|
+
if (m = line.match(/@return\s+\[([^\]]+)\]/))
|
|
388
|
+
return_type = m[1]
|
|
389
|
+
end
|
|
390
|
+
end
|
|
360
391
|
has_private ||= line.match?(/^\s*#\s*@private\b/)
|
|
361
392
|
has_protected ||= line.match?(/^\s*#\s*@protected\b/)
|
|
362
393
|
has_module_function_note ||= line.match?(/^\s*#\s*@note\s+module_function:/)
|
|
@@ -366,7 +397,9 @@ module Docscribe
|
|
|
366
397
|
|
|
367
398
|
{
|
|
368
399
|
param_names: param_names,
|
|
400
|
+
param_types: param_types,
|
|
369
401
|
has_return: has_return,
|
|
402
|
+
return_type: return_type,
|
|
370
403
|
raise_types: raise_types,
|
|
371
404
|
has_private: has_private,
|
|
372
405
|
has_protected: has_protected,
|
|
@@ -462,6 +495,19 @@ module Docscribe
|
|
|
462
495
|
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
463
496
|
)
|
|
464
497
|
param_types[pname] = ty
|
|
498
|
+
|
|
499
|
+
when :kwoptarg
|
|
500
|
+
pname, default = *a
|
|
501
|
+
pname = pname.to_s
|
|
502
|
+
default_src = default&.loc&.expression&.source
|
|
503
|
+
ty = external_sig&.param_types&.[](pname) ||
|
|
504
|
+
Infer.infer_param_type(
|
|
505
|
+
"#{pname}:",
|
|
506
|
+
default_src,
|
|
507
|
+
fallback_type: config.fallback_type,
|
|
508
|
+
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
509
|
+
)
|
|
510
|
+
param_types[pname] = ty
|
|
465
511
|
end
|
|
466
512
|
end
|
|
467
513
|
|
|
@@ -672,6 +718,17 @@ module Docscribe
|
|
|
672
718
|
nil
|
|
673
719
|
end
|
|
674
720
|
|
|
721
|
+
# Method documentation.
|
|
722
|
+
#
|
|
723
|
+
# @note module_function: when included, also defines #extract_param_type_from_param_line (instance visibility: private)
|
|
724
|
+
# @param [Object] line Param documentation.
|
|
725
|
+
# @return [Object]
|
|
726
|
+
def extract_param_type_from_param_line(line)
|
|
727
|
+
if (m = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
|
|
728
|
+
m[1]
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
|
|
675
732
|
# Build a Plugin::Context from a collected insertion.
|
|
676
733
|
#
|
|
677
734
|
# @note module_function
|
|
@@ -83,20 +83,11 @@ module Docscribe
|
|
|
83
83
|
|
|
84
84
|
config ||= Docscribe::Config.load
|
|
85
85
|
signature_provider = build_signature_provider(config, code, file.to_s)
|
|
86
|
-
|
|
87
|
-
if config.respond_to?(:core_rbs_provider)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
core_rbs_provider = nil
|
|
92
|
-
end
|
|
93
|
-
elsif config.respond_to?(:rbs_provider)
|
|
94
|
-
begin
|
|
95
|
-
core_rbs_provider = config.rbs_provider
|
|
96
|
-
rescue StandardError
|
|
97
|
-
core_rbs_provider = nil
|
|
98
|
-
end
|
|
99
|
-
end
|
|
86
|
+
begin
|
|
87
|
+
core_rbs_provider ||= config.core_rbs_provider if config.respond_to?(:core_rbs_provider)
|
|
88
|
+
rescue StandardError => e
|
|
89
|
+
warn "Docscribe: failed to load core RBS provider: #{e.message}" if ENV['DOCSCRIBE_DEBUG']
|
|
90
|
+
core_rbs_provider = nil
|
|
100
91
|
end
|
|
101
92
|
|
|
102
93
|
collector = Docscribe::InlineRewriter::Collector.new(buffer)
|
|
@@ -345,8 +336,14 @@ module Docscribe
|
|
|
345
336
|
rewriter.remove(range)
|
|
346
337
|
end
|
|
347
338
|
|
|
339
|
+
effective_param_types = external_sig&.param_types || DocBuilder.build_param_types_from_node(
|
|
340
|
+
insertion.node,
|
|
341
|
+
external_sig: external_sig,
|
|
342
|
+
config: config
|
|
343
|
+
)
|
|
344
|
+
|
|
348
345
|
doc = build_method_doc(insertion, config: config, signature_provider: signature_provider,
|
|
349
|
-
core_rbs_provider: core_rbs_provider, param_types:
|
|
346
|
+
core_rbs_provider: core_rbs_provider, param_types: effective_param_types)
|
|
350
347
|
return if doc.nil? || doc.empty?
|
|
351
348
|
|
|
352
349
|
rewriter.insert_before(anchor_bol_range, doc)
|
|
@@ -369,7 +366,8 @@ module Docscribe
|
|
|
369
366
|
config: config,
|
|
370
367
|
signature_provider: signature_provider,
|
|
371
368
|
core_rbs_provider: core_rbs_provider,
|
|
372
|
-
param_types: external_sig&.param_types
|
|
369
|
+
param_types: external_sig&.param_types,
|
|
370
|
+
strategy: strategy
|
|
373
371
|
)
|
|
374
372
|
|
|
375
373
|
missing_lines = merge_result[:lines]
|
|
@@ -397,24 +395,28 @@ module Docscribe
|
|
|
397
395
|
range = Parser::Source::Range.new(buffer, info[:start_pos], info[:end_pos])
|
|
398
396
|
rewriter.replace(range, new_block)
|
|
399
397
|
|
|
400
|
-
|
|
398
|
+
if existing_order_changed
|
|
401
399
|
add_change(
|
|
402
400
|
changes,
|
|
403
|
-
type:
|
|
401
|
+
type: :unsorted_tags,
|
|
404
402
|
insertion: insertion,
|
|
405
403
|
file: file,
|
|
406
|
-
message:
|
|
407
|
-
extra: reason[:extra] || {}
|
|
404
|
+
message: 'unsorted tags'
|
|
408
405
|
)
|
|
409
406
|
end
|
|
407
|
+
end
|
|
410
408
|
|
|
411
|
-
|
|
409
|
+
type_mismatch_reasons = reason_specs.select { |r| %i[updated_param updated_return].include?(r[:type]) }
|
|
410
|
+
|
|
411
|
+
if new_block != old_block || type_mismatch_reasons.any?
|
|
412
|
+
reason_specs.each do |reason|
|
|
412
413
|
add_change(
|
|
413
414
|
changes,
|
|
414
|
-
type: :
|
|
415
|
+
type: reason[:type],
|
|
415
416
|
insertion: insertion,
|
|
416
417
|
file: file,
|
|
417
|
-
message:
|
|
418
|
+
message: reason[:message],
|
|
419
|
+
extra: reason[:extra] || {}
|
|
418
420
|
)
|
|
419
421
|
end
|
|
420
422
|
end
|
|
@@ -423,7 +425,8 @@ module Docscribe
|
|
|
423
425
|
end
|
|
424
426
|
|
|
425
427
|
doc = build_method_doc(insertion, config: config, signature_provider: signature_provider,
|
|
426
|
-
core_rbs_provider: core_rbs_provider,
|
|
428
|
+
core_rbs_provider: core_rbs_provider,
|
|
429
|
+
param_types: external_sig&.param_types)
|
|
427
430
|
return if doc.nil? || doc.empty?
|
|
428
431
|
|
|
429
432
|
rewriter.insert_before(anchor_bol_range, doc)
|
|
@@ -790,16 +793,18 @@ module Docscribe
|
|
|
790
793
|
# @param [Object, nil] signature_provider external signature provider
|
|
791
794
|
# @param [Object, nil] core_rbs_provider RBS core type provider
|
|
792
795
|
# @param [Hash, nil] param_types parameter name -> type map
|
|
796
|
+
# @param [Object] strategy Param documentation.
|
|
793
797
|
# @return [Hash] result with `:lines` and `:reasons` keys
|
|
794
798
|
def build_missing_method_merge_result(insertion, existing_lines:, config:, signature_provider:,
|
|
795
|
-
core_rbs_provider:, param_types:)
|
|
799
|
+
core_rbs_provider:, param_types:, strategy:)
|
|
796
800
|
DocBuilder.build_missing_merge_result(
|
|
797
801
|
insertion,
|
|
798
802
|
existing_lines: existing_lines,
|
|
799
803
|
config: config,
|
|
800
804
|
signature_provider: signature_provider,
|
|
801
805
|
core_rbs_provider: core_rbs_provider,
|
|
802
|
-
param_types: param_types
|
|
806
|
+
param_types: param_types,
|
|
807
|
+
strategy: strategy
|
|
803
808
|
)
|
|
804
809
|
end
|
|
805
810
|
|
|
@@ -41,8 +41,6 @@ module Docscribe
|
|
|
41
41
|
# - :anchor_node => Parser::AST::Node — node above which to insert doc
|
|
42
42
|
# - :doc => String — complete doc block including newlines
|
|
43
43
|
#
|
|
44
|
-
# @param [Parser::AST::Node] ast root AST node of the file
|
|
45
|
-
# @param [Parser::Source::Buffer] buffer source buffer
|
|
46
44
|
# @param [Object] _ast Param documentation.
|
|
47
45
|
# @param [Object] _buffer Param documentation.
|
|
48
46
|
# @return [Array<Hash>]
|
|
@@ -89,10 +89,27 @@ module Docscribe
|
|
|
89
89
|
# @param [Symbol] scope
|
|
90
90
|
# @return [Object]
|
|
91
91
|
def definition_for(container:, scope:)
|
|
92
|
-
type_name =
|
|
92
|
+
type_name = parse_type_name(absolute_const(container))
|
|
93
93
|
scope == :class ? @builder.build_singleton(type_name) : @builder.build_instance(type_name)
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Parse a fully-qualified constant string into an RBS TypeName.
|
|
97
|
+
#
|
|
98
|
+
# Uses the lower-level constructor so it works across RBS versions
|
|
99
|
+
# that may not expose `TypeName.parse`.
|
|
100
|
+
#
|
|
101
|
+
# @private
|
|
102
|
+
# @param [String] string e.g. "::Irb::Autosuggestions"
|
|
103
|
+
# @return [::RBS::TypeName]
|
|
104
|
+
def parse_type_name(string)
|
|
105
|
+
absolute = string.start_with?('::')
|
|
106
|
+
*path, name = string.delete_prefix('::').split('::').map(&:to_sym)
|
|
107
|
+
::RBS::TypeName.new(
|
|
108
|
+
name: name,
|
|
109
|
+
namespace: ::RBS::Namespace.new(path: path, absolute: absolute)
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
96
113
|
# Normalize a container name into an absolute constant path.
|
|
97
114
|
#
|
|
98
115
|
# @private
|
data/lib/docscribe/version.rb
CHANGED
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.3.
|
|
4
|
+
version: 1.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- unurgunite
|
|
@@ -213,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
213
213
|
- !ruby/object:Gem::Version
|
|
214
214
|
version: '0'
|
|
215
215
|
requirements: []
|
|
216
|
-
rubygems_version: 4.0.
|
|
216
|
+
rubygems_version: 4.0.12
|
|
217
217
|
specification_version: 4
|
|
218
218
|
summary: Auto-generate inline YARD documentation for Ruby by analyzing code AST. Supports
|
|
219
219
|
RBS and Sorbet type signatures.
|