docscribe 1.4.2 → 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.
- checksums.yaml +4 -4
- data/README.md +601 -139
- data/exe/docscribe-client +105 -0
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +107 -53
- data/lib/docscribe/cli/formatters/json.rb +294 -0
- data/lib/docscribe/cli/formatters/sarif.rb +235 -0
- data/lib/docscribe/cli/formatters/text.rb +208 -0
- data/lib/docscribe/cli/formatters.rb +26 -0
- data/lib/docscribe/cli/generate.rb +56 -62
- data/lib/docscribe/cli/init.rb +14 -6
- data/lib/docscribe/cli/options.rb +206 -89
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +433 -154
- data/lib/docscribe/cli/server.rb +135 -0
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +21 -24
- data/lib/docscribe/config/defaults.rb +7 -2
- data/lib/docscribe/config/emit.rb +17 -0
- data/lib/docscribe/config/filtering.rb +17 -24
- data/lib/docscribe/config/loader.rb +19 -17
- data/lib/docscribe/config/plugin.rb +1 -1
- data/lib/docscribe/config/rbs.rb +39 -7
- data/lib/docscribe/config/sorbet.rb +22 -16
- data/lib/docscribe/config/sorting.rb +1 -1
- data/lib/docscribe/config/template.rb +10 -1
- data/lib/docscribe/config/utils.rb +11 -9
- data/lib/docscribe/config.rb +10 -6
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/literals.rb +6 -11
- data/lib/docscribe/infer/names.rb +2 -3
- data/lib/docscribe/infer/params.rb +14 -16
- data/lib/docscribe/infer/raises.rb +3 -5
- data/lib/docscribe/infer/returns.rb +615 -151
- data/lib/docscribe/infer.rb +29 -26
- data/lib/docscribe/inline_rewriter/collector.rb +159 -164
- data/lib/docscribe/inline_rewriter/doc_block.rb +145 -115
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1032 -723
- data/lib/docscribe/inline_rewriter/source_helpers.rb +48 -48
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +82 -85
- data/lib/docscribe/inline_rewriter.rb +485 -488
- data/lib/docscribe/lru_cache.rb +49 -0
- data/lib/docscribe/parsing.rb +28 -9
- data/lib/docscribe/plugin/base/collector_plugin.rb +2 -1
- data/lib/docscribe/plugin/base/tag_plugin.rb +0 -1
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +25 -26
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +17 -16
- data/lib/docscribe/server.rb +608 -0
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -2
- data/lib/docscribe/types/rbs/provider.rb +177 -51
- data/lib/docscribe/types/rbs/type_formatter.rb +224 -83
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +29 -21
- data/lib/docscribe/types/sorbet/rbi_provider.rb +6 -5
- data/lib/docscribe/types/sorbet/source_provider.rb +6 -4
- data/lib/docscribe/types/yard/formatter.rb +100 -0
- data/lib/docscribe/types/yard/parser.rb +240 -0
- data/lib/docscribe/types/yard/types.rb +52 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +38 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docscribe
|
|
4
|
+
module CLI
|
|
5
|
+
module Formatters
|
|
6
|
+
# Text output formatter preserving the original CLI output format.
|
|
7
|
+
class Text
|
|
8
|
+
# Format and print check summary.
|
|
9
|
+
#
|
|
10
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
11
|
+
# @param [Docscribe::CLI::Formatters::opts] options runtime options hash
|
|
12
|
+
# @return [void]
|
|
13
|
+
def format_check_summary(state:, options:)
|
|
14
|
+
puts
|
|
15
|
+
format_fail_paths(state, options)
|
|
16
|
+
format_check_status_line(state)
|
|
17
|
+
format_type_mismatch_paths(state, options)
|
|
18
|
+
format_error_paths(state)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Format and print write summary.
|
|
22
|
+
#
|
|
23
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
24
|
+
# @param [Docscribe::CLI::Formatters::opts] options runtime options hash
|
|
25
|
+
# @return [void]
|
|
26
|
+
def format_write_summary(state:, options:)
|
|
27
|
+
puts
|
|
28
|
+
puts "Docscribe: updated #{state[:corrected]} file(s)" if state[:corrected].positive?
|
|
29
|
+
format_corrected_paths(state, options)
|
|
30
|
+
|
|
31
|
+
return unless state[:had_errors]
|
|
32
|
+
|
|
33
|
+
warn "Docscribe: #{state[:error_paths].size} file(s) had errors"
|
|
34
|
+
format_error_paths(state)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Print files needing updates.
|
|
38
|
+
#
|
|
39
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
40
|
+
# @param [Docscribe::CLI::Formatters::opts] options runtime options hash
|
|
41
|
+
# @return [void]
|
|
42
|
+
def format_fail_paths(state, options)
|
|
43
|
+
state[:fail_paths].each do |p|
|
|
44
|
+
puts "Would update: #{p}"
|
|
45
|
+
|
|
46
|
+
next if options[:verbose] || options[:quiet]
|
|
47
|
+
|
|
48
|
+
Array(state[:fail_changes][p]).each do |change|
|
|
49
|
+
puts " - #{format_change_reason(change)}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Print check status line.
|
|
55
|
+
#
|
|
56
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
57
|
+
# @return [void]
|
|
58
|
+
def format_check_status_line(state)
|
|
59
|
+
checked_error = state[:error_paths].size
|
|
60
|
+
type_mismatch_count = state[:type_mismatch_paths].size
|
|
61
|
+
|
|
62
|
+
if all_fine?(state, checked_error, type_mismatch_count)
|
|
63
|
+
puts "Docscribe: OK (#{state[:checked_ok]} files checked)"
|
|
64
|
+
elsif mismatch_only?(state, checked_error)
|
|
65
|
+
puts "Docscribe: OK (#{state[:checked_ok]} files checked, #{type_mismatch_count} with type mismatches)"
|
|
66
|
+
else
|
|
67
|
+
puts failure_line(state, type_mismatch_count, checked_error)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Print type mismatch warnings.
|
|
72
|
+
#
|
|
73
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
74
|
+
# @param [Docscribe::CLI::Formatters::opts] options runtime options hash
|
|
75
|
+
# @return [void]
|
|
76
|
+
def format_type_mismatch_paths(state, options)
|
|
77
|
+
return if options[:quiet]
|
|
78
|
+
return unless options[:verbose] || options[:explain]
|
|
79
|
+
|
|
80
|
+
state[:type_mismatch_paths].each do |p|
|
|
81
|
+
warn "Type mismatches: #{p}"
|
|
82
|
+
Array(state[:type_mismatch_changes][p]).each do |change|
|
|
83
|
+
warn " - #{format_change_reason(change)}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Print updated file paths.
|
|
89
|
+
#
|
|
90
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
91
|
+
# @param [Docscribe::CLI::Formatters::opts] options runtime options hash
|
|
92
|
+
# @return [void]
|
|
93
|
+
def format_corrected_paths(state, options)
|
|
94
|
+
state[:corrected_paths].each do |p|
|
|
95
|
+
puts "Updated: #{p}"
|
|
96
|
+
|
|
97
|
+
next if options[:verbose] || options[:quiet]
|
|
98
|
+
|
|
99
|
+
Array(state[:corrected_changes][p]).each do |change|
|
|
100
|
+
puts " - #{format_change_reason(change)}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Print error file messages.
|
|
106
|
+
#
|
|
107
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
108
|
+
# @return [void]
|
|
109
|
+
def format_error_paths(state)
|
|
110
|
+
return if state[:error_paths].empty?
|
|
111
|
+
|
|
112
|
+
warn ''
|
|
113
|
+
state[:error_paths].each do |p|
|
|
114
|
+
warn "Error processing: #{p}"
|
|
115
|
+
warn " #{state[:error_messages][p]}" if state[:error_messages][p]
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
# Check if all files passed.
|
|
122
|
+
#
|
|
123
|
+
# @private
|
|
124
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
125
|
+
# @param [Integer] checked_error count of error files
|
|
126
|
+
# @param [Integer] type_mismatch_count count of type mismatches
|
|
127
|
+
# @return [Boolean]
|
|
128
|
+
def all_fine?(state, checked_error, type_mismatch_count)
|
|
129
|
+
state[:checked_fail].zero? && checked_error.zero? && type_mismatch_count.zero?
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Check only type mismatches.
|
|
133
|
+
#
|
|
134
|
+
# @private
|
|
135
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
136
|
+
# @param [Integer] checked_error count of error files
|
|
137
|
+
# @return [Boolean]
|
|
138
|
+
def mismatch_only?(state, checked_error)
|
|
139
|
+
state[:checked_fail].zero? && checked_error.zero?
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Build failure status line.
|
|
143
|
+
#
|
|
144
|
+
# @private
|
|
145
|
+
# @param [Docscribe::CLI::Formatters::state] state formatter state hash
|
|
146
|
+
# @param [Integer] type_mismatch_count count of type mismatches
|
|
147
|
+
# @param [Integer] checked_error count of error files
|
|
148
|
+
# @return [String]
|
|
149
|
+
def failure_line(state, type_mismatch_count, checked_error)
|
|
150
|
+
parts = ["#{state[:checked_fail]} need updates"]
|
|
151
|
+
parts << "#{type_mismatch_count} type mismatches" if type_mismatch_count.positive?
|
|
152
|
+
parts << "#{checked_error} errors"
|
|
153
|
+
parts << "#{state[:checked_ok]} ok"
|
|
154
|
+
"Docscribe: FAILED (#{parts.join(', ')})"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Format change reason string.
|
|
158
|
+
#
|
|
159
|
+
# @private
|
|
160
|
+
# @param [Docscribe::CLI::Formatters::change] change change info hash
|
|
161
|
+
# @return [String]
|
|
162
|
+
def format_change_reason(change)
|
|
163
|
+
line = change_line_suffix(change)
|
|
164
|
+
method = change_method_suffix(change)
|
|
165
|
+
|
|
166
|
+
return "unsorted tags#{line}" if change[:type] == :unsorted_tags
|
|
167
|
+
return "#{change[:message]}#{method}#{line}" if direct_message_change?(change)
|
|
168
|
+
|
|
169
|
+
"#{change[:message] || change[:type].to_s.tr('_', ' ')}#{method}#{line}"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Build change line suffix.
|
|
173
|
+
#
|
|
174
|
+
# @private
|
|
175
|
+
# @param [Docscribe::CLI::Formatters::change] change change info hash
|
|
176
|
+
# @return [String]
|
|
177
|
+
def change_line_suffix(change)
|
|
178
|
+
change[:line] ? " at line #{change[:line]}" : ''
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Build change method suffix.
|
|
182
|
+
#
|
|
183
|
+
# @private
|
|
184
|
+
# @param [Docscribe::CLI::Formatters::change] change change info hash
|
|
185
|
+
# @return [String]
|
|
186
|
+
def change_method_suffix(change)
|
|
187
|
+
change[:method] ? " for #{change[:method]}" : ''
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Check direct message type.
|
|
191
|
+
#
|
|
192
|
+
# @private
|
|
193
|
+
# @param [Docscribe::CLI::Formatters::change] change change info hash
|
|
194
|
+
# @return [Boolean]
|
|
195
|
+
def direct_message_change?(change)
|
|
196
|
+
%i[
|
|
197
|
+
missing_param
|
|
198
|
+
missing_return
|
|
199
|
+
missing_raise
|
|
200
|
+
missing_visibility
|
|
201
|
+
missing_module_function_note
|
|
202
|
+
insert_full_doc_block
|
|
203
|
+
].include?(change[:type])
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docscribe
|
|
4
|
+
module CLI
|
|
5
|
+
# Factory for output formatters.
|
|
6
|
+
module Formatters
|
|
7
|
+
# Select formatter by format type.
|
|
8
|
+
#
|
|
9
|
+
# @param [Docscribe::CLI::Formatters::format] format output format symbol
|
|
10
|
+
# @raise [ArgumentError]
|
|
11
|
+
# @return [Docscribe::CLI::Formatters::Text, Docscribe::CLI::Formatters::Json, Docscribe::CLI::Formatters::Sarif]
|
|
12
|
+
def self.for(format)
|
|
13
|
+
case format
|
|
14
|
+
when :text then Text.new
|
|
15
|
+
when :json then Json.new
|
|
16
|
+
when :sarif then Sarif.new
|
|
17
|
+
else raise ArgumentError, "Unknown format: #{format}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
require_relative 'formatters/text'
|
|
25
|
+
require_relative 'formatters/json'
|
|
26
|
+
require_relative 'formatters/sarif'
|
|
@@ -12,6 +12,16 @@ module Docscribe
|
|
|
12
12
|
# docscribe generate tag MyPlugin --output lib/docscribe_plugins
|
|
13
13
|
# docscribe generate tag MyPlugin --stdout
|
|
14
14
|
module Generate
|
|
15
|
+
BANNER = <<~TEXT
|
|
16
|
+
Usage: docscribe generate <type> <PluginName> [options]
|
|
17
|
+
|
|
18
|
+
Types:
|
|
19
|
+
tag Generate a TagPlugin skeleton
|
|
20
|
+
collector Generate a CollectorPlugin skeleton
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
TEXT
|
|
24
|
+
|
|
15
25
|
PLUGIN_TYPES = %w[tag collector].freeze
|
|
16
26
|
|
|
17
27
|
NEXT_STEPS_TEMPLATE = <<~TEXT
|
|
@@ -34,8 +44,7 @@ module Docscribe
|
|
|
34
44
|
class << self
|
|
35
45
|
# Run the `generate` subcommand.
|
|
36
46
|
#
|
|
37
|
-
# @param [Array<String>] argv
|
|
38
|
-
# @raise [OptionParser::InvalidOption]
|
|
47
|
+
# @param [Array<String>] argv command line arguments
|
|
39
48
|
# @return [Integer] exit code
|
|
40
49
|
def run(argv)
|
|
41
50
|
opts, parser = parse_generate_options(argv)
|
|
@@ -54,9 +63,9 @@ module Docscribe
|
|
|
54
63
|
# Parse options for the generate subcommand.
|
|
55
64
|
#
|
|
56
65
|
# @private
|
|
57
|
-
# @param [Array<String>] argv
|
|
66
|
+
# @param [Array<String>] argv command line arguments
|
|
58
67
|
# @raise [OptionParser::InvalidOption]
|
|
59
|
-
# @return [
|
|
68
|
+
# @return [(Hash<Symbol, Object>, OptionParser)]
|
|
60
69
|
def parse_generate_options(argv)
|
|
61
70
|
opts = { output: nil, stdout: false, help: false }
|
|
62
71
|
parser = build_option_parser(opts)
|
|
@@ -74,8 +83,8 @@ module Docscribe
|
|
|
74
83
|
# Extract plugin_type and class_name from remaining argv.
|
|
75
84
|
#
|
|
76
85
|
# @private
|
|
77
|
-
# @param [Array<String>] argv
|
|
78
|
-
# @return [
|
|
86
|
+
# @param [Array<String>] argv command line arguments
|
|
87
|
+
# @return [(String?, String?)]
|
|
79
88
|
def extract_generate_args(argv)
|
|
80
89
|
[argv.shift, argv.shift]
|
|
81
90
|
end
|
|
@@ -83,9 +92,9 @@ module Docscribe
|
|
|
83
92
|
# Validate generate arguments and return exit code on failure.
|
|
84
93
|
#
|
|
85
94
|
# @private
|
|
86
|
-
# @param [String
|
|
87
|
-
# @param [String
|
|
88
|
-
# @param [OptionParser] parser
|
|
95
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
96
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
97
|
+
# @param [OptionParser] parser option parser instance
|
|
89
98
|
# @return [Integer, nil] exit code or nil if valid
|
|
90
99
|
def validate_generate_args(plugin_type, class_name, parser)
|
|
91
100
|
return 1 unless args_provided?(plugin_type, class_name, parser)
|
|
@@ -98,9 +107,9 @@ module Docscribe
|
|
|
98
107
|
# Render plugin boilerplate for the given type and class name.
|
|
99
108
|
#
|
|
100
109
|
# @private
|
|
101
|
-
# @param [String] plugin_type 'tag' or 'collector'
|
|
102
|
-
# @param [String] class_name
|
|
103
|
-
# @return [String]
|
|
110
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
111
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
112
|
+
# @return [String?]
|
|
104
113
|
def render(plugin_type, class_name)
|
|
105
114
|
case plugin_type
|
|
106
115
|
when 'tag' then tag_template(class_name)
|
|
@@ -111,7 +120,7 @@ module Docscribe
|
|
|
111
120
|
# Template for a TagPlugin.
|
|
112
121
|
#
|
|
113
122
|
# @private
|
|
114
|
-
# @param [String] class_name
|
|
123
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
115
124
|
# @return [String]
|
|
116
125
|
def tag_template(class_name)
|
|
117
126
|
<<~RUBY
|
|
@@ -169,7 +178,7 @@ module Docscribe
|
|
|
169
178
|
# Template for a CollectorPlugin.
|
|
170
179
|
#
|
|
171
180
|
# @private
|
|
172
|
-
# @param [String] class_name
|
|
181
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
173
182
|
# @return [String]
|
|
174
183
|
def collector_template(class_name)
|
|
175
184
|
<<~RUBY
|
|
@@ -237,10 +246,10 @@ module Docscribe
|
|
|
237
246
|
# Write generated plugin to a file or print to STDOUT based on options.
|
|
238
247
|
#
|
|
239
248
|
# @private
|
|
240
|
-
# @param [String] content generated plugin source code
|
|
241
|
-
# @param [String] plugin_type 'tag' or 'collector'
|
|
242
|
-
# @param [String] class_name CamelCase plugin class name
|
|
243
|
-
# @param [Hash] opts parsed options hash
|
|
249
|
+
# @param [String?] content generated plugin source code
|
|
250
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
251
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
252
|
+
# @param [Hash<Symbol, Object>] opts parsed options hash
|
|
244
253
|
# @return [Integer] exit code
|
|
245
254
|
def dispatch_output(content, plugin_type, class_name, opts)
|
|
246
255
|
if opts[:stdout]
|
|
@@ -254,10 +263,10 @@ module Docscribe
|
|
|
254
263
|
# Write the generated content to a file.
|
|
255
264
|
#
|
|
256
265
|
# @private
|
|
257
|
-
# @param [String] content
|
|
258
|
-
# @param [String] plugin_type
|
|
259
|
-
# @param [String] class_name
|
|
260
|
-
# @param [String] output_dir
|
|
266
|
+
# @param [String?] content file content to write
|
|
267
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
268
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
269
|
+
# @param [String?] output_dir output directory path
|
|
261
270
|
# @return [Integer] exit code
|
|
262
271
|
def write_plugin(content, plugin_type:, class_name:, output_dir:)
|
|
263
272
|
path = plugin_path(class_name, output_dir)
|
|
@@ -272,38 +281,22 @@ module Docscribe
|
|
|
272
281
|
# Build the OptionParser for the generate subcommand.
|
|
273
282
|
#
|
|
274
283
|
# @private
|
|
275
|
-
# @param [Hash] opts mutable parsed options hash
|
|
284
|
+
# @param [Hash<Symbol, Object>] opts mutable parsed options hash
|
|
276
285
|
# @return [OptionParser]
|
|
277
286
|
def build_option_parser(opts)
|
|
278
287
|
OptionParser.new do |opt|
|
|
279
|
-
opt.banner =
|
|
288
|
+
opt.banner = BANNER
|
|
280
289
|
register_output_option(opt, opts)
|
|
281
290
|
register_stdout_option(opt, opts)
|
|
282
291
|
register_help_option(opt, opts)
|
|
283
292
|
end
|
|
284
293
|
end
|
|
285
294
|
|
|
286
|
-
# Return the usage banner for the generate subcommand parser.
|
|
287
|
-
#
|
|
288
|
-
# @private
|
|
289
|
-
# @return [String]
|
|
290
|
-
def parser_banner
|
|
291
|
-
<<~TEXT
|
|
292
|
-
Usage: docscribe generate <type> <PluginName> [options]
|
|
293
|
-
|
|
294
|
-
Types:
|
|
295
|
-
tag Generate a TagPlugin skeleton
|
|
296
|
-
collector Generate a CollectorPlugin skeleton
|
|
297
|
-
|
|
298
|
-
Options:
|
|
299
|
-
TEXT
|
|
300
|
-
end
|
|
301
|
-
|
|
302
295
|
# Register the --output option on the OptionParser.
|
|
303
296
|
#
|
|
304
297
|
# @private
|
|
305
|
-
# @param [OptionParser] opt
|
|
306
|
-
# @param [Hash] opts mutable parsed options hash
|
|
298
|
+
# @param [OptionParser] opt option parser instance
|
|
299
|
+
# @param [Hash<Symbol, Object>] opts mutable parsed options hash
|
|
307
300
|
# @return [void]
|
|
308
301
|
def register_output_option(opt, opts)
|
|
309
302
|
opt.on('--output DIR', 'Directory to write the plugin file (default: .)') { |v| opts[:output] = v }
|
|
@@ -312,8 +305,8 @@ module Docscribe
|
|
|
312
305
|
# Register the --stdout option on the OptionParser.
|
|
313
306
|
#
|
|
314
307
|
# @private
|
|
315
|
-
# @param [OptionParser] opt
|
|
316
|
-
# @param [Hash] opts mutable parsed options hash
|
|
308
|
+
# @param [OptionParser] opt option parser instance
|
|
309
|
+
# @param [Hash<Symbol, Object>] opts mutable parsed options hash
|
|
317
310
|
# @return [void]
|
|
318
311
|
def register_stdout_option(opt, opts)
|
|
319
312
|
opt.on('--stdout', 'Print the generated plugin to STDOUT instead of writing a file') { opts[:stdout] = true }
|
|
@@ -322,11 +315,12 @@ module Docscribe
|
|
|
322
315
|
# Register the -h/--help option on the OptionParser.
|
|
323
316
|
#
|
|
324
317
|
# @private
|
|
325
|
-
# @param [OptionParser] opt
|
|
326
|
-
# @param [Hash] opts mutable parsed options hash
|
|
318
|
+
# @param [OptionParser] opt option parser instance
|
|
319
|
+
# @param [Hash<Symbol, Object>] opts mutable parsed options hash
|
|
327
320
|
# @return [void]
|
|
328
321
|
def register_help_option(opt, opts)
|
|
329
322
|
opt.on('-h', '--help', 'Show this help') do
|
|
323
|
+
puts opt
|
|
330
324
|
opts[:help] = true
|
|
331
325
|
end
|
|
332
326
|
end
|
|
@@ -334,9 +328,9 @@ module Docscribe
|
|
|
334
328
|
# Validate that both plugin_type and class_name arguments were provided.
|
|
335
329
|
#
|
|
336
330
|
# @private
|
|
337
|
-
# @param [String
|
|
338
|
-
# @param [String
|
|
339
|
-
# @param [OptionParser] parser
|
|
331
|
+
# @param [String?] plugin_type plugin type argument
|
|
332
|
+
# @param [String?] class_name plugin class name argument
|
|
333
|
+
# @param [OptionParser] parser option parser instance
|
|
340
334
|
# @return [Boolean]
|
|
341
335
|
def args_provided?(plugin_type, class_name, parser)
|
|
342
336
|
return true if plugin_type && class_name
|
|
@@ -349,7 +343,7 @@ module Docscribe
|
|
|
349
343
|
# Validate that the plugin type is one of the recognized types.
|
|
350
344
|
#
|
|
351
345
|
# @private
|
|
352
|
-
# @param [String] plugin_type plugin type to validate
|
|
346
|
+
# @param [String?] plugin_type plugin type to validate
|
|
353
347
|
# @return [Boolean]
|
|
354
348
|
def known_type?(plugin_type)
|
|
355
349
|
return true if PLUGIN_TYPES.include?(plugin_type)
|
|
@@ -361,7 +355,7 @@ module Docscribe
|
|
|
361
355
|
# Validate that the class name is a valid Ruby constant name.
|
|
362
356
|
#
|
|
363
357
|
# @private
|
|
364
|
-
# @param [String] class_name class name to validate
|
|
358
|
+
# @param [String?] class_name class name to validate
|
|
365
359
|
# @return [Boolean]
|
|
366
360
|
def valid_name?(class_name)
|
|
367
361
|
return true if valid_constant?(class_name)
|
|
@@ -373,7 +367,7 @@ module Docscribe
|
|
|
373
367
|
# Check whether a string is a valid Ruby constant name.
|
|
374
368
|
#
|
|
375
369
|
# @private
|
|
376
|
-
# @param [String] str
|
|
370
|
+
# @param [String?] str string constant to validate
|
|
377
371
|
# @return [Boolean]
|
|
378
372
|
def valid_constant?(str)
|
|
379
373
|
!!(str =~ /\A[A-Z][A-Za-z0-9]*(?:::[A-Z][A-Za-z0-9]*)*\z/)
|
|
@@ -382,8 +376,8 @@ module Docscribe
|
|
|
382
376
|
# Build the file path for the generated plugin.
|
|
383
377
|
#
|
|
384
378
|
# @private
|
|
385
|
-
# @param [String] class_name CamelCase plugin class name
|
|
386
|
-
# @param [String] output_dir output directory
|
|
379
|
+
# @param [String?] class_name CamelCase plugin class name
|
|
380
|
+
# @param [String?] output_dir output directory
|
|
387
381
|
# @return [String] full file path
|
|
388
382
|
def plugin_path(class_name, output_dir)
|
|
389
383
|
File.join(output_dir || '.', "#{underscore(class_name || '')}.rb")
|
|
@@ -392,7 +386,7 @@ module Docscribe
|
|
|
392
386
|
# Convert CamelCase to snake_case for file naming.
|
|
393
387
|
#
|
|
394
388
|
# @private
|
|
395
|
-
# @param [String] str
|
|
389
|
+
# @param [String] str CamelCase string to convert
|
|
396
390
|
# @return [String]
|
|
397
391
|
def underscore(str)
|
|
398
392
|
str
|
|
@@ -416,9 +410,9 @@ module Docscribe
|
|
|
416
410
|
# Create the output directory and write the plugin file.
|
|
417
411
|
#
|
|
418
412
|
# @private
|
|
419
|
-
# @param [String] output_dir output directory path
|
|
413
|
+
# @param [String?] output_dir output directory path
|
|
420
414
|
# @param [String] path full plugin file path
|
|
421
|
-
# @param [String] content file content to write
|
|
415
|
+
# @param [String?] content file content to write
|
|
422
416
|
# @return [void]
|
|
423
417
|
def write_to_file(output_dir, path, content)
|
|
424
418
|
require 'fileutils'
|
|
@@ -429,7 +423,7 @@ module Docscribe
|
|
|
429
423
|
# Print the creation message and next steps after generating a plugin.
|
|
430
424
|
#
|
|
431
425
|
# @private
|
|
432
|
-
# @param [String] plugin_type 'tag' or 'collector'
|
|
426
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
433
427
|
# @param [String] path file path of the created plugin
|
|
434
428
|
# @return [void]
|
|
435
429
|
def print_created(plugin_type, path)
|
|
@@ -441,8 +435,8 @@ module Docscribe
|
|
|
441
435
|
# Print registration instructions after file creation.
|
|
442
436
|
#
|
|
443
437
|
# @private
|
|
444
|
-
# @param [String] plugin_type
|
|
445
|
-
# @param [String] path
|
|
438
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
439
|
+
# @param [String] path file path
|
|
446
440
|
# @return [String]
|
|
447
441
|
def next_steps(plugin_type, path)
|
|
448
442
|
format(NEXT_STEPS_TEMPLATE,
|
|
@@ -464,8 +458,8 @@ module Docscribe
|
|
|
464
458
|
# Generate an implementation hint string for the given plugin type.
|
|
465
459
|
#
|
|
466
460
|
# @private
|
|
467
|
-
# @param [String] plugin_type 'tag' or 'collector'
|
|
468
|
-
# @return [String] hint text
|
|
461
|
+
# @param [String?] plugin_type 'tag' or 'collector'
|
|
462
|
+
# @return [String, nil] hint text
|
|
469
463
|
def generate_implement_hint(plugin_type)
|
|
470
464
|
case plugin_type
|
|
471
465
|
when 'tag'
|
data/lib/docscribe/cli/init.rb
CHANGED
|
@@ -7,6 +7,14 @@ module Docscribe
|
|
|
7
7
|
module CLI
|
|
8
8
|
# Generate starter Docscribe configuration.
|
|
9
9
|
module Init
|
|
10
|
+
BANNER = <<~TEXT
|
|
11
|
+
Usage: docscribe init [options]
|
|
12
|
+
|
|
13
|
+
Generate a starter docscribe.yml configuration file.
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
TEXT
|
|
17
|
+
|
|
10
18
|
class << self
|
|
11
19
|
# Create or print a starter Docscribe configuration file.
|
|
12
20
|
#
|
|
@@ -37,8 +45,8 @@ module Docscribe
|
|
|
37
45
|
# Parse CLI options for `docscribe init`.
|
|
38
46
|
#
|
|
39
47
|
# @private
|
|
40
|
-
# @param [Array<String>] argv
|
|
41
|
-
# @return [Hash] parsed options
|
|
48
|
+
# @param [Array<String>] argv command-line arguments for `docscribe init`
|
|
49
|
+
# @return [Hash<Symbol, Object>] parsed options
|
|
42
50
|
def parse_init_options(argv)
|
|
43
51
|
opts = default_init_options
|
|
44
52
|
build_init_parser(opts).parse!(argv)
|
|
@@ -48,7 +56,7 @@ module Docscribe
|
|
|
48
56
|
# Return the default options hash for the init command.
|
|
49
57
|
#
|
|
50
58
|
# @private
|
|
51
|
-
# @return [Hash]
|
|
59
|
+
# @return [Hash<Symbol, String, Boolean>]
|
|
52
60
|
def default_init_options
|
|
53
61
|
{ config: 'docscribe.yml', force: false, stdout: false, help: false }
|
|
54
62
|
end
|
|
@@ -56,11 +64,11 @@ module Docscribe
|
|
|
56
64
|
# Build and return an OptionParser for the init command.
|
|
57
65
|
#
|
|
58
66
|
# @private
|
|
59
|
-
# @param [Hash] opts options hash that the parser populates
|
|
67
|
+
# @param [Hash<Symbol, Object>] opts options hash that the parser populates
|
|
60
68
|
# @return [OptionParser]
|
|
61
69
|
def build_init_parser(opts)
|
|
62
70
|
OptionParser.new do |o|
|
|
63
|
-
o.banner =
|
|
71
|
+
o.banner = BANNER
|
|
64
72
|
o.on('--config PATH', 'Where to write the config (default: docscribe.yml)') { |v| opts[:config] = v }
|
|
65
73
|
o.on('-f', '--force', 'Overwrite if the file already exists') { opts[:force] = true }
|
|
66
74
|
o.on('--stdout', 'Print config template to STDOUT instead of writing a file') { opts[:stdout] = true }
|
|
@@ -74,7 +82,7 @@ module Docscribe
|
|
|
74
82
|
# Write the config template to a file.
|
|
75
83
|
#
|
|
76
84
|
# @private
|
|
77
|
-
# @param [Hash] opts parsed options
|
|
85
|
+
# @param [Hash<Symbol, Object>] opts parsed options
|
|
78
86
|
# @param [String] yaml config template content
|
|
79
87
|
# @return [Integer] exit code
|
|
80
88
|
def write_init_config(opts, yaml)
|