docscribe 1.4.1 → 1.5.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 +588 -104
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +180 -36
- 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 +296 -125
- data/lib/docscribe/cli/init.rb +58 -14
- data/lib/docscribe/cli/options.rb +410 -133
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +503 -189
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +35 -9
- data/lib/docscribe/config/defaults.rb +16 -12
- data/lib/docscribe/config/emit.rb +18 -0
- data/lib/docscribe/config/filtering.rb +37 -31
- data/lib/docscribe/config/loader.rb +20 -13
- data/lib/docscribe/config/plugin.rb +2 -1
- data/lib/docscribe/config/rbs.rb +68 -27
- data/lib/docscribe/config/sorbet.rb +40 -17
- data/lib/docscribe/config/sorting.rb +2 -1
- data/lib/docscribe/config/template.rb +10 -1
- data/lib/docscribe/config/utils.rb +12 -9
- data/lib/docscribe/config.rb +3 -4
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +39 -26
- data/lib/docscribe/infer/names.rb +24 -16
- data/lib/docscribe/infer/params.rb +57 -13
- data/lib/docscribe/infer/raises.rb +23 -15
- data/lib/docscribe/infer/returns.rb +784 -199
- data/lib/docscribe/infer.rb +28 -28
- data/lib/docscribe/inline_rewriter/collector.rb +816 -430
- data/lib/docscribe/inline_rewriter/doc_block.rb +323 -150
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1837 -648
- data/lib/docscribe/inline_rewriter/source_helpers.rb +119 -71
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +165 -107
- data/lib/docscribe/inline_rewriter.rb +1144 -727
- data/lib/docscribe/parsing.rb +29 -10
- data/lib/docscribe/plugin/base/collector_plugin.rb +3 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -2
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +49 -23
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +54 -22
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -3
- data/lib/docscribe/types/rbs/provider.rb +127 -62
- data/lib/docscribe/types/rbs/type_formatter.rb +286 -77
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +51 -27
- data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
- data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
- 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 +34 -2
|
@@ -17,38 +17,51 @@ module Docscribe
|
|
|
17
17
|
#
|
|
18
18
|
# If the node does not match a supported pattern, the fallback type is returned.
|
|
19
19
|
#
|
|
20
|
-
# @note module_function:
|
|
20
|
+
# @note module_function: defines #type_from_literal (visibility: private)
|
|
21
21
|
# @param [Parser::AST::Node, nil] node literal/value node
|
|
22
22
|
# @param [String] fallback_type type returned when inference is uncertain
|
|
23
23
|
# @return [String]
|
|
24
24
|
def type_from_literal(node, fallback_type: FALLBACK_TYPE)
|
|
25
25
|
return fallback_type unless node
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
27
|
+
literal_type_for(node.type) || const_type_for(node, fallback_type) ||
|
|
28
|
+
send_new_type_for(node, fallback_type) || fallback_type
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Map a node type symbol to a known literal type name.
|
|
32
|
+
#
|
|
33
|
+
# @note module_function: defines #literal_type_for (visibility: private)
|
|
34
|
+
# @param [Symbol] type node type
|
|
35
|
+
# @return [String, nil]
|
|
36
|
+
def literal_type_for(type)
|
|
37
|
+
LITERAL_TYPE_MAP[type]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Extract a constant name from a `:const` node.
|
|
41
|
+
#
|
|
42
|
+
# @note module_function: defines #const_type_for (visibility: private)
|
|
43
|
+
# @param [Parser::AST::Node] node literal/value node
|
|
44
|
+
# @param [String] _fallback_type fallback type string (unused here)
|
|
45
|
+
# @return [String, nil]
|
|
46
|
+
def const_type_for(node, _fallback_type)
|
|
47
|
+
return unless node.type == :const
|
|
48
|
+
|
|
49
|
+
node.children.last.to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Extract a type from a `Foo.new` send node.
|
|
53
|
+
#
|
|
54
|
+
# @note module_function: defines #send_new_type_for (visibility: private)
|
|
55
|
+
# @param [Parser::AST::Node] node literal/value node
|
|
56
|
+
# @param [String] _fallback_type fallback type string (unused here)
|
|
57
|
+
# @return [String, nil]
|
|
58
|
+
def send_new_type_for(node, _fallback_type)
|
|
59
|
+
return unless node.type == :send
|
|
60
|
+
|
|
61
|
+
recv, meth, = node.children
|
|
62
|
+
return unless meth == :new && recv&.type == :const
|
|
63
|
+
|
|
64
|
+
recv.children.last.to_s
|
|
52
65
|
end
|
|
53
66
|
end
|
|
54
67
|
end
|
|
@@ -15,27 +15,35 @@ module Docscribe
|
|
|
15
15
|
#
|
|
16
16
|
# Returns nil for unsupported nodes.
|
|
17
17
|
#
|
|
18
|
-
# @note module_function:
|
|
19
|
-
# @param [Parser::AST::Node, nil]
|
|
18
|
+
# @note module_function: defines #const_full_name (visibility: private)
|
|
19
|
+
# @param [Parser::AST::Node, nil] node constant-like AST node
|
|
20
20
|
# @return [String, nil]
|
|
21
|
-
def const_full_name(
|
|
22
|
-
return nil unless
|
|
21
|
+
def const_full_name(node)
|
|
22
|
+
return nil unless node.is_a?(Parser::AST::Node)
|
|
23
23
|
|
|
24
|
-
case
|
|
24
|
+
case node.type
|
|
25
25
|
when :const
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
build_const_full_name(node)
|
|
27
|
+
when :cbase
|
|
28
|
+
''
|
|
29
|
+
end
|
|
30
|
+
end
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
# Build the fully qualified name from a `:const` node.
|
|
33
|
+
#
|
|
34
|
+
# @note module_function: defines #build_const_full_name (visibility: private)
|
|
35
|
+
# @param [Parser::AST::Node] node a `:const` node
|
|
36
|
+
# @return [String]
|
|
37
|
+
def build_const_full_name(node)
|
|
38
|
+
scope, name = *node
|
|
39
|
+
scope_name = const_full_name(scope)
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
if scope_name && !scope_name.empty?
|
|
42
|
+
"#{scope_name}::#{name}"
|
|
43
|
+
elsif scope_name == ''
|
|
44
|
+
"::#{name}"
|
|
45
|
+
else
|
|
46
|
+
name.to_s
|
|
39
47
|
end
|
|
40
48
|
end
|
|
41
49
|
end
|
|
@@ -15,46 +15,90 @@ module Docscribe
|
|
|
15
15
|
# - special-casing `options:` as `Hash` when enabled
|
|
16
16
|
# - literal defaults via AST parsing
|
|
17
17
|
#
|
|
18
|
-
# @note module_function:
|
|
18
|
+
# @note module_function: defines #infer_param_type (visibility: private)
|
|
19
19
|
# @param [String] name parameter name as used internally (may include `*`, `**`, `&`, or trailing `:`)
|
|
20
|
-
# @param [String
|
|
20
|
+
# @param [String?] default_str source for the default value expression
|
|
21
21
|
# @param [String] fallback_type type returned when inference is uncertain
|
|
22
22
|
# @param [Boolean] treat_options_keyword_as_hash whether `options:` should
|
|
23
|
-
# be treated specially as Hash
|
|
24
23
|
# @return [String]
|
|
25
24
|
def infer_param_type(name, default_str, fallback_type: FALLBACK_TYPE, treat_options_keyword_as_hash: true)
|
|
25
|
+
prefix_param_type(name) || inferred_param_type(name, default_str, fallback_type,
|
|
26
|
+
treat_options_keyword_as_hash: treat_options_keyword_as_hash)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Return type for special parameter prefixes.
|
|
30
|
+
#
|
|
31
|
+
# @note module_function: defines #prefix_param_type (visibility: private)
|
|
32
|
+
# @param [String] name parameter name
|
|
33
|
+
# @return [String, nil]
|
|
34
|
+
def prefix_param_type(name)
|
|
26
35
|
return 'Array' if name.start_with?('*') && !name.start_with?('**')
|
|
27
36
|
return 'Hash' if name.start_with?('**')
|
|
28
37
|
return 'Proc' if name.start_with?('&')
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
ty = Literals.type_from_literal(node, fallback_type: fallback_type)
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
# Infer type for a regular or keyword parameter with optional default.
|
|
43
|
+
#
|
|
44
|
+
# @note module_function: defines #inferred_param_type (visibility: private)
|
|
45
|
+
# @param [String] name parameter name
|
|
46
|
+
# @param [String?] default_str default expression source
|
|
47
|
+
# @param [String] fallback_type type returned when not special-cased
|
|
48
|
+
# @param [Boolean] treat_options_keyword_as_hash whether to treat 'options:' as Hash
|
|
49
|
+
# @return [String]
|
|
50
|
+
def inferred_param_type(name, default_str, fallback_type, treat_options_keyword_as_hash:)
|
|
51
|
+
if name.end_with?(':') && default_str.nil?
|
|
52
|
+
return options_keyword_type(name, treat_options_keyword_as_hash, fallback_type)
|
|
36
53
|
end
|
|
37
54
|
|
|
38
|
-
|
|
55
|
+
node = parse_expr(default_str)
|
|
56
|
+
ty = Literals.type_from_literal(node, fallback_type: fallback_type)
|
|
57
|
+
|
|
58
|
+
return 'Hash' if options_hash_keyword?(name, default_str, ty, treat_options_keyword_as_hash)
|
|
39
59
|
|
|
40
60
|
ty
|
|
41
61
|
end
|
|
42
62
|
|
|
63
|
+
# Return 'Hash' for a keyword parameter named 'options:' when special-cased, else fallback.
|
|
64
|
+
#
|
|
65
|
+
# @note module_function: defines #options_keyword_type (visibility: private)
|
|
66
|
+
# @param [String] name parameter name
|
|
67
|
+
# @param [Boolean] treat_options_keyword_as_hash whether to treat 'options:' as Hash
|
|
68
|
+
# @param [String] fallback_type type returned when not special-cased
|
|
69
|
+
# @return [String]
|
|
70
|
+
def options_keyword_type(name, treat_options_keyword_as_hash, fallback_type)
|
|
71
|
+
treat_options_keyword_as_hash && name == 'options:' ? 'Hash' : fallback_type
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Whether a keyword parameter named 'options:' with a hash default should be typed as Hash.
|
|
75
|
+
#
|
|
76
|
+
# @note module_function: defines #options_hash_keyword? (visibility: private)
|
|
77
|
+
# @param [String] name parameter name
|
|
78
|
+
# @param [String?] default_str default expression source
|
|
79
|
+
# @param [String] type inferred type
|
|
80
|
+
# @param [Boolean] treat_options_keyword_as_hash whether to treat 'options:' as Hash
|
|
81
|
+
# @return [Boolean]
|
|
82
|
+
def options_hash_keyword?(name, default_str, type, treat_options_keyword_as_hash)
|
|
83
|
+
treat_options_keyword_as_hash && name == 'options:' && (default_str == '{}' || type == 'Hash')
|
|
84
|
+
end
|
|
85
|
+
|
|
43
86
|
# Parse a standalone expression for parameter-default inference.
|
|
44
87
|
#
|
|
45
88
|
# Returns nil if the expression is empty or cannot be parsed.
|
|
46
89
|
#
|
|
47
|
-
# @note module_function:
|
|
48
|
-
# @param [String
|
|
90
|
+
# @note module_function: defines #parse_expr (visibility: private)
|
|
91
|
+
# @param [String?] src expression source
|
|
49
92
|
# @raise [Parser::SyntaxError]
|
|
50
|
-
# @return [Parser::AST::Node, nil]
|
|
93
|
+
# @return [Parser::AST::Node, nil] if Parser::SyntaxError
|
|
94
|
+
# @return [nil] if Parser::SyntaxError
|
|
51
95
|
def parse_expr(src)
|
|
52
96
|
return nil if src.nil? || src.strip.empty?
|
|
53
97
|
|
|
54
98
|
buffer = Parser::Source::Buffer.new('(param)')
|
|
55
99
|
buffer.source = src
|
|
56
100
|
Docscribe::Parsing.parse_buffer(buffer)
|
|
57
|
-
rescue Parser::SyntaxError
|
|
101
|
+
rescue Parser::SyntaxError # steep:ignore
|
|
58
102
|
nil
|
|
59
103
|
end
|
|
60
104
|
end
|
|
@@ -16,28 +16,18 @@ module Docscribe
|
|
|
16
16
|
#
|
|
17
17
|
# Returns unique exception names in discovery order.
|
|
18
18
|
#
|
|
19
|
-
# @note module_function:
|
|
19
|
+
# @note module_function: defines #infer_raises_from_node (visibility: private)
|
|
20
20
|
# @param [Parser::AST::Node] node method or expression node to inspect
|
|
21
21
|
# @return [Array<String>]
|
|
22
22
|
def infer_raises_from_node(node)
|
|
23
|
-
raises = []
|
|
23
|
+
raises = [] #: Array[String]
|
|
24
24
|
|
|
25
25
|
ASTWalk.walk(node) do |n|
|
|
26
26
|
case n.type
|
|
27
27
|
when :resbody
|
|
28
|
-
|
|
29
|
-
raises.concat(exception_names_from_rescue_list(exc_list))
|
|
30
|
-
|
|
28
|
+
raises.concat(exception_names_from_rescue_list(n.children[0]))
|
|
31
29
|
when :send
|
|
32
|
-
|
|
33
|
-
next unless recv.nil? && %i[raise fail].include?(meth)
|
|
34
|
-
|
|
35
|
-
if args.empty?
|
|
36
|
-
raises << DEFAULT_ERROR
|
|
37
|
-
else
|
|
38
|
-
c = Names.const_full_name(args[0])
|
|
39
|
-
raises << (c || DEFAULT_ERROR)
|
|
40
|
-
end
|
|
30
|
+
collect_send_raise(raises, n)
|
|
41
31
|
end
|
|
42
32
|
end
|
|
43
33
|
|
|
@@ -51,7 +41,7 @@ module Docscribe
|
|
|
51
41
|
# - `Foo` => `["Foo"]`
|
|
52
42
|
# - `[Foo, Bar]` => `["Foo", "Bar"]`
|
|
53
43
|
#
|
|
54
|
-
# @note module_function:
|
|
44
|
+
# @note module_function: defines #exception_names_from_rescue_list (visibility: private)
|
|
55
45
|
# @param [Parser::AST::Node, nil] exc_list rescue exception list node
|
|
56
46
|
# @return [Array<String>]
|
|
57
47
|
def exception_names_from_rescue_list(exc_list)
|
|
@@ -63,6 +53,24 @@ module Docscribe
|
|
|
63
53
|
[Names.const_full_name(exc_list) || DEFAULT_ERROR]
|
|
64
54
|
end
|
|
65
55
|
end
|
|
56
|
+
|
|
57
|
+
# Collect exception names from a `raise` or `fail` send node.
|
|
58
|
+
#
|
|
59
|
+
# @note module_function: defines #collect_send_raise (visibility: private)
|
|
60
|
+
# @param [Array<String>] raises accumulator
|
|
61
|
+
# @param [Parser::AST::Node] node send node
|
|
62
|
+
# @return [void]
|
|
63
|
+
def collect_send_raise(raises, node)
|
|
64
|
+
recv, meth, *args = *node
|
|
65
|
+
return unless recv.nil? && %i[raise fail].include?(meth)
|
|
66
|
+
|
|
67
|
+
if args.empty?
|
|
68
|
+
raises << DEFAULT_ERROR
|
|
69
|
+
else
|
|
70
|
+
c = Names.const_full_name(args[0])
|
|
71
|
+
raises << (c || DEFAULT_ERROR)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
66
74
|
end
|
|
67
75
|
end
|
|
68
76
|
end
|