decode 0.24.3 → 0.24.4
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
- checksums.yaml.gz.sig +0 -0
- data/bake/decode/rbs.rb +1 -1
- data/context/coverage.md +1 -1
- data/context/getting-started.md +1 -1
- data/context/ruby-documentation.md +3 -3
- data/context/types.md +127 -0
- data/lib/decode/comment/attribute.rb +4 -1
- data/lib/decode/comment/constant.rb +47 -0
- data/lib/decode/comment/node.rb +32 -12
- data/lib/decode/comment/option.rb +1 -1
- data/lib/decode/comment/parameter.rb +5 -1
- data/lib/decode/comment/rbs.rb +8 -8
- data/lib/decode/comment/tag.rb +13 -1
- data/lib/decode/comment/tags.rb +16 -5
- data/lib/decode/comment/text.rb +1 -0
- data/lib/decode/comment/yields.rb +5 -1
- data/lib/decode/definition.rb +33 -31
- data/lib/decode/documentation.rb +10 -5
- data/lib/decode/index.rb +12 -7
- data/lib/decode/language/generic.rb +10 -1
- data/lib/decode/language/reference.rb +7 -4
- data/lib/decode/language/ruby/class.rb +2 -2
- data/lib/decode/language/ruby/code.rb +21 -3
- data/lib/decode/language/ruby/definition.rb +15 -3
- data/lib/decode/language/ruby/generic.rb +2 -1
- data/lib/decode/language/ruby/parser.rb +132 -91
- data/lib/decode/language/ruby/reference.rb +4 -1
- data/lib/decode/language/ruby/segment.rb +2 -2
- data/lib/decode/languages.rb +29 -8
- data/lib/decode/location.rb +12 -1
- data/lib/decode/rbs/class.rb +91 -14
- data/lib/decode/rbs/generator.rb +67 -11
- data/lib/decode/rbs/method.rb +394 -68
- data/lib/decode/rbs/module.rb +81 -5
- data/lib/decode/rbs/type.rb +51 -0
- data/lib/decode/rbs/wrapper.rb +10 -3
- data/lib/decode/scope.rb +2 -2
- data/lib/decode/segment.rb +3 -2
- data/lib/decode/source.rb +5 -14
- data/lib/decode/syntax/rewriter.rb +4 -1
- data/lib/decode/trie.rb +29 -21
- data/lib/decode/version.rb +2 -1
- data/readme.md +6 -0
- data/releases.md +6 -0
- data/sig/decode.rbs +501 -113
- data.tar.gz.sig +0 -0
- metadata +4 -1
- metadata.gz.sig +0 -0
data/lib/decode/rbs/class.rb
CHANGED
@@ -19,15 +19,15 @@ module Decode
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Extract generic type parameters from the class definition.
|
22
|
-
# @returns [Array] The generic type parameters for this class.
|
22
|
+
# @returns [Array[Symbol]] The generic type parameters for this class.
|
23
23
|
def generics
|
24
24
|
@generics ||= extract_generics
|
25
25
|
end
|
26
26
|
|
27
27
|
# Convert the class definition to RBS AST
|
28
|
-
def to_rbs_ast(method_definitions = [], index = nil)
|
28
|
+
def to_rbs_ast(method_definitions = [], constant_definitions = [], attribute_definitions = [], index = nil)
|
29
29
|
name = simple_name_to_rbs(@definition.name)
|
30
|
-
comment =
|
30
|
+
comment = self.comment
|
31
31
|
|
32
32
|
# Extract generics from RBS tags
|
33
33
|
type_params = generics.map do |generic|
|
@@ -39,24 +39,30 @@ module Decode
|
|
39
39
|
)
|
40
40
|
end
|
41
41
|
|
42
|
-
# Build method definitions
|
42
|
+
# Build method definitions:
|
43
43
|
methods = method_definitions.map{|method_def| Method.new(method_def).to_rbs_ast(index)}.compact
|
44
44
|
|
45
|
-
#
|
45
|
+
# Build constant definitions:
|
46
|
+
constants = constant_definitions.map{|const_def| build_constant_rbs(const_def)}.compact
|
47
|
+
|
48
|
+
# Build attribute definitions and infer instance variable types:
|
49
|
+
attributes, instance_variables = build_attributes_rbs(attribute_definitions)
|
50
|
+
|
51
|
+
# Extract super class if present:
|
46
52
|
super_class = if @definition.super_class
|
47
53
|
::RBS::AST::Declarations::Class::Super.new(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
name: qualified_name_to_rbs(@definition.super_class),
|
55
|
+
args: [],
|
56
|
+
location: nil
|
57
|
+
)
|
52
58
|
end
|
53
59
|
|
54
|
-
# Create the class declaration with generics
|
60
|
+
# Create the class declaration with generics:
|
55
61
|
::RBS::AST::Declarations::Class.new(
|
56
62
|
name: name,
|
57
63
|
type_params: type_params,
|
58
64
|
super_class: super_class,
|
59
|
-
members: methods,
|
65
|
+
members: constants + attributes + instance_variables + methods,
|
60
66
|
annotations: [],
|
61
67
|
location: nil,
|
62
68
|
comment: comment
|
@@ -69,18 +75,89 @@ module Decode
|
|
69
75
|
tags.select(&:generic?).map(&:generic_parameter)
|
70
76
|
end
|
71
77
|
|
72
|
-
#
|
78
|
+
# Build a constant RBS declaration.
|
79
|
+
def build_constant_rbs(constant_definition)
|
80
|
+
# Look for @constant tags in the constant's documentation:
|
81
|
+
documentation = constant_definition.documentation
|
82
|
+
constant_tags = documentation&.filter(Decode::Comment::Constant)&.to_a
|
83
|
+
|
84
|
+
if constant_tags&.any?
|
85
|
+
type_string = constant_tags.first.type.strip
|
86
|
+
type = ::Decode::RBS::Type.parse(type_string)
|
87
|
+
|
88
|
+
::RBS::AST::Declarations::Constant.new(
|
89
|
+
name: constant_definition.name.to_sym,
|
90
|
+
type: type,
|
91
|
+
location: nil,
|
92
|
+
comment: nil
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Convert a simple name to RBS TypeName (not qualified).
|
73
98
|
def simple_name_to_rbs(name)
|
74
99
|
::RBS::TypeName.new(name: name.to_sym, namespace: ::RBS::Namespace.empty)
|
75
100
|
end
|
76
101
|
|
102
|
+
# Build attribute RBS declarations and infer instance variable types.
|
103
|
+
# @parameter attribute_definitions [Array] Array of Attribute definition objects
|
104
|
+
# @returns [Array] A tuple of [attribute_declarations, instance_variable_declarations]
|
105
|
+
def build_attributes_rbs(attribute_definitions)
|
106
|
+
attributes = []
|
107
|
+
instance_variables = []
|
108
|
+
|
109
|
+
# Create a mapping from attribute names to their types:
|
110
|
+
attribute_types = {}
|
111
|
+
|
112
|
+
attribute_definitions.each do |attr_def|
|
113
|
+
# Extract @attribute type annotation from documentation:
|
114
|
+
documentation = attr_def.documentation
|
115
|
+
attribute_tags = documentation&.filter(Decode::Comment::Attribute)&.to_a
|
116
|
+
|
117
|
+
if attribute_tags&.any?
|
118
|
+
type_string = attribute_tags.first.type.strip
|
119
|
+
type = ::Decode::RBS::Type.parse(type_string)
|
120
|
+
|
121
|
+
attribute_types[attr_def.name] = type
|
122
|
+
|
123
|
+
# Generate attr_reader RBS declaration:
|
124
|
+
attributes << ::RBS::AST::Members::AttrReader.new(
|
125
|
+
name: attr_def.name.to_sym,
|
126
|
+
type: type,
|
127
|
+
ivar_name: :"@#{attr_def.name}",
|
128
|
+
kind: :instance,
|
129
|
+
annotations: [],
|
130
|
+
location: nil,
|
131
|
+
comment: nil
|
132
|
+
)
|
133
|
+
|
134
|
+
# Generate instance variable declaration:
|
135
|
+
instance_variables << ::RBS::AST::Members::InstanceVariable.new(
|
136
|
+
name: :"@#{attr_def.name}",
|
137
|
+
type: type,
|
138
|
+
location: nil,
|
139
|
+
comment: nil
|
140
|
+
)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
[attributes, instance_variables]
|
145
|
+
end
|
146
|
+
|
77
147
|
# Convert a qualified name to RBS TypeName
|
78
148
|
def qualified_name_to_rbs(qualified_name)
|
79
149
|
parts = qualified_name.split("::")
|
80
150
|
name = parts.pop
|
81
|
-
namespace = ::RBS::Namespace.new(path: parts.map(&:to_sym), absolute: true)
|
82
151
|
|
83
|
-
|
152
|
+
# For simple names (no ::), create relative references within current namespace:
|
153
|
+
if parts.empty?
|
154
|
+
::RBS::TypeName.new(name: name.to_sym, namespace: ::RBS::Namespace.empty)
|
155
|
+
else
|
156
|
+
# For qualified names within the same root namespace, use relative references.
|
157
|
+
# This handles cases like `Comment::Node`, `Language::Generic` within `Decode` module.
|
158
|
+
namespace = ::RBS::Namespace.new(path: parts.map(&:to_sym), absolute: false)
|
159
|
+
::RBS::TypeName.new(name: name.to_sym, namespace: namespace)
|
160
|
+
end
|
84
161
|
end
|
85
162
|
|
86
163
|
end
|
data/lib/decode/rbs/generator.rb
CHANGED
@@ -14,19 +14,30 @@ module Decode
|
|
14
14
|
class Generator
|
15
15
|
# Initialize a new RBS generator.
|
16
16
|
# Sets up the RBS environment for type resolution.
|
17
|
-
|
17
|
+
# @parameter include_private [bool] Whether to include private methods in RBS output.
|
18
|
+
def initialize(include_private: false)
|
18
19
|
# Set up RBS environment for type resolution
|
19
20
|
@loader = ::RBS::EnvironmentLoader.new()
|
20
21
|
@environment = ::RBS::Environment.from_loader(@loader).resolve_type_names
|
22
|
+
@include_private = include_private
|
21
23
|
end
|
22
24
|
|
25
|
+
# @attribute [::RBS::EnvironmentLoader] The RBS environment loader.
|
26
|
+
attr :loader
|
27
|
+
|
28
|
+
# @attribute [::RBS::Environment] The resolved RBS environment.
|
29
|
+
attr :environment
|
30
|
+
|
31
|
+
# @attribute [bool] Whether to include private methods.
|
32
|
+
attr :include_private
|
33
|
+
|
23
34
|
# Generate RBS declarations for the given index.
|
24
35
|
# @parameter index [Decode::Index] The index containing definitions to generate RBS for.
|
25
36
|
# @parameter output [IO] The output stream to write to.
|
26
37
|
def generate(index, output: $stdout)
|
27
38
|
# Build nested RBS AST structure using a hash for proper ||= behavior
|
28
|
-
declarations = {}
|
29
|
-
roots = {}
|
39
|
+
declarations = {} #: Hash[Array[Symbol], untyped]
|
40
|
+
roots = {} #: Hash[Array[Symbol], untyped]
|
30
41
|
|
31
42
|
# Efficiently traverse the trie to find containers and their methods
|
32
43
|
index.trie.traverse do |lexical_path, node, descend|
|
@@ -58,8 +69,10 @@ module Decode
|
|
58
69
|
private
|
59
70
|
|
60
71
|
# Build nested RBS declarations preserving the parent hierarchy.
|
61
|
-
# @
|
62
|
-
# @
|
72
|
+
# @parameter definition [Definition] The definition to build RBS for.
|
73
|
+
# @parameter declarations [Hash] The declarations hash to store results.
|
74
|
+
# @parameter index [Index] The index containing all definitions.
|
75
|
+
# @returns [untyped?] If the definition has no parent, returns the declaration, otherwise nil.
|
63
76
|
def build_nested_declaration(definition, declarations, index)
|
64
77
|
# Create the declaration for this definition using ||= to avoid duplicates
|
65
78
|
qualified_name = definition.qualified_name
|
@@ -81,22 +94,65 @@ module Decode
|
|
81
94
|
end
|
82
95
|
end
|
83
96
|
|
84
|
-
# Convert a definition to RBS AST
|
97
|
+
# Convert a definition to RBS AST.
|
98
|
+
# @parameter definition [Definition] The definition to convert.
|
99
|
+
# @parameter index [Index] The index containing all definitions.
|
100
|
+
# @returns [untyped] The RBS AST declaration.
|
85
101
|
def definition_to_rbs(definition, index)
|
102
|
+
methods = get_methods_for_definition(definition, index)
|
103
|
+
constants = get_constants_for_definition(definition, index)
|
104
|
+
attributes = get_attributes_for_definition(definition, index)
|
105
|
+
|
86
106
|
case definition
|
87
107
|
when Decode::Language::Ruby::Class
|
88
|
-
Class.new(definition).to_rbs_ast(
|
108
|
+
Class.new(definition).to_rbs_ast(methods, constants, attributes, index)
|
89
109
|
when Decode::Language::Ruby::Module
|
90
|
-
Module.new(definition).to_rbs_ast(
|
110
|
+
Module.new(definition).to_rbs_ast(methods, constants, attributes, index)
|
91
111
|
end
|
92
112
|
end
|
93
113
|
|
94
|
-
# Get methods for a given definition efficiently using trie lookup
|
114
|
+
# Get methods for a given definition efficiently using trie lookup.
|
115
|
+
# @parameter definition [Definition] The definition to get methods for.
|
116
|
+
# @parameter index [Index] The index containing all definitions.
|
117
|
+
# @returns [Array] Array of method definitions.
|
95
118
|
def get_methods_for_definition(definition, index)
|
96
119
|
# Use the trie to efficiently find methods for this definition
|
97
120
|
if node = index.trie.lookup(definition.full_path)
|
98
121
|
node.children.flat_map do |name, child|
|
99
|
-
child.values.select
|
122
|
+
child.values.select do |symbol|
|
123
|
+
symbol.is_a?(Decode::Language::Ruby::Method) &&
|
124
|
+
(symbol.public? || symbol.protected? || (@include_private && symbol.private?))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
else
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Get constants for a given definition efficiently using trie lookup.
|
133
|
+
# @parameter definition [Definition] The definition to get constants for.
|
134
|
+
# @parameter index [Index] The index containing all definitions.
|
135
|
+
# @returns [Array] Array of constant definitions.
|
136
|
+
def get_constants_for_definition(definition, index)
|
137
|
+
# Use the trie to efficiently find constants for this definition
|
138
|
+
if node = index.trie.lookup(definition.full_path)
|
139
|
+
node.children.flat_map do |name, child|
|
140
|
+
child.values.select{|symbol| symbol.is_a?(Decode::Language::Ruby::Constant)}
|
141
|
+
end
|
142
|
+
else
|
143
|
+
[]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get attributes for a given definition efficiently using trie lookup.
|
148
|
+
# @parameter definition [Definition] The definition to get attributes for.
|
149
|
+
# @parameter index [Index] The index containing all definitions.
|
150
|
+
# @returns [Array] Array of attribute definitions.
|
151
|
+
def get_attributes_for_definition(definition, index)
|
152
|
+
# Use the trie to efficiently find attributes for this definition
|
153
|
+
if node = index.trie.lookup(definition.full_path)
|
154
|
+
node.children.flat_map do |name, child|
|
155
|
+
child.values.select{|symbol| symbol.is_a?(Decode::Language::Ruby::Attribute)}
|
100
156
|
end
|
101
157
|
else
|
102
158
|
[]
|
@@ -104,4 +160,4 @@ module Decode
|
|
104
160
|
end
|
105
161
|
end
|
106
162
|
end
|
107
|
-
end
|
163
|
+
end
|