kanayago 0.1.1 → 0.2.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -0
  3. data/.ruby-version +1 -0
  4. data/README.md +20 -29
  5. data/Rakefile +43 -96
  6. data/ext/kanayago/extconf.rb +6 -0
  7. data/ext/kanayago/id.h +12 -5
  8. data/ext/kanayago/id_table.h +15 -0
  9. data/ext/kanayago/include/ruby/st.h +199 -0
  10. data/ext/kanayago/internal/array.h +3 -0
  11. data/ext/kanayago/internal/basic_operators.h +1 -0
  12. data/ext/kanayago/internal/bignum.h +1 -0
  13. data/ext/kanayago/internal/bits.h +82 -0
  14. data/ext/kanayago/internal/encoding.h +4 -1
  15. data/ext/kanayago/internal/error.h +33 -0
  16. data/ext/kanayago/internal/fixnum.h +1 -0
  17. data/ext/kanayago/internal/gc.h +47 -11
  18. data/ext/kanayago/internal/hash.h +3 -0
  19. data/ext/kanayago/internal/imemo.h +93 -32
  20. data/ext/kanayago/internal/io.h +30 -7
  21. data/ext/kanayago/internal/namespace.h +81 -0
  22. data/ext/kanayago/internal/numeric.h +1 -0
  23. data/ext/kanayago/internal/parse.h +17 -3
  24. data/ext/kanayago/internal/re.h +7 -2
  25. data/ext/kanayago/internal/sanitizers.h +88 -39
  26. data/ext/kanayago/internal/set_table.h +70 -0
  27. data/ext/kanayago/internal/string.h +33 -16
  28. data/ext/kanayago/internal/symbol.h +4 -3
  29. data/ext/kanayago/internal/thread.h +42 -9
  30. data/ext/kanayago/internal/variable.h +13 -11
  31. data/ext/kanayago/internal/vm.h +4 -5
  32. data/ext/kanayago/internal.h +0 -3
  33. data/ext/kanayago/kanayago.c +554 -235
  34. data/ext/kanayago/kanayago.h +5 -0
  35. data/ext/kanayago/literal_node.c +343 -0
  36. data/ext/kanayago/literal_node.h +30 -0
  37. data/ext/kanayago/method.h +18 -2
  38. data/ext/kanayago/node.c +7 -1
  39. data/ext/kanayago/node.h +14 -3
  40. data/ext/kanayago/parse.c +7602 -7156
  41. data/ext/kanayago/parse.h +39 -39
  42. data/ext/kanayago/parser_st.c +2 -1
  43. data/ext/kanayago/pattern_node.c +78 -0
  44. data/ext/kanayago/pattern_node.h +13 -0
  45. data/ext/kanayago/ruby_atomic.h +43 -0
  46. data/ext/kanayago/ruby_parser.c +7 -35
  47. data/ext/kanayago/rubyparser.h +83 -80
  48. data/ext/kanayago/scope_node.c +34 -0
  49. data/ext/kanayago/scope_node.h +8 -0
  50. data/ext/kanayago/shape.h +321 -111
  51. data/ext/kanayago/st.c +905 -21
  52. data/ext/kanayago/statement_node.c +795 -0
  53. data/ext/kanayago/statement_node.h +66 -0
  54. data/ext/kanayago/string_node.c +192 -0
  55. data/ext/kanayago/string_node.h +19 -0
  56. data/ext/kanayago/symbol.h +2 -9
  57. data/ext/kanayago/thread_pthread.h +10 -3
  58. data/ext/kanayago/universal_parser.c +1 -20
  59. data/ext/kanayago/variable_node.c +72 -0
  60. data/ext/kanayago/variable_node.h +12 -0
  61. data/ext/kanayago/vm_core.h +205 -71
  62. data/lib/kanayago/literal_node.rb +87 -0
  63. data/lib/kanayago/pattern_node.rb +19 -0
  64. data/lib/kanayago/statement_node.rb +222 -0
  65. data/lib/kanayago/string_node.rb +43 -0
  66. data/lib/kanayago/variable_node.rb +23 -0
  67. data/lib/kanayago/version.rb +1 -1
  68. data/lib/kanayago.rb +22 -0
  69. data/patch/3.4/copy_target.rb +78 -0
  70. data/patch/3.4/kanayago.patch +162 -0
  71. data/patch/head/copy_target.rb +84 -0
  72. data/patch/head/kanayago.patch +162 -0
  73. data/sample/minitest_generator.rb +266 -0
  74. data/sample/test_generator.rb +272 -0
  75. data/typeprof.conf.json +9 -0
  76. metadata +32 -4
  77. data/ext/kanayago/parse.tmp.y +0 -16145
@@ -0,0 +1,272 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/kanayago'
4
+
5
+ class TestGenerator
6
+ def initialize(code)
7
+ @code = code
8
+ @ast = Kanayago.parse(code)
9
+ @current_visibility = :public
10
+ end
11
+
12
+ def generate
13
+ class_infos = extract_classes(@ast)
14
+
15
+ return '# No classes found in the code' if class_infos.empty?
16
+
17
+ # Generate tests for all classes
18
+ class_infos.map { |class_info| generate_rspec(class_info) }.join("\n\n")
19
+ end
20
+
21
+ private
22
+
23
+ # rubocop:disable Metrics/CyclomaticComplexity
24
+ def extract_classes(node, namespace = [])
25
+ classes = []
26
+
27
+ case node
28
+ when Kanayago::ModuleNode
29
+ # Process module and its contents
30
+ module_name = extract_constant_name(node.cpath)
31
+ new_namespace = namespace + [module_name]
32
+ classes.concat(extract_classes(node.body, new_namespace)) if node.respond_to?(:body)
33
+
34
+ when Kanayago::ClassNode
35
+ # Process class and collect its methods
36
+ class_name = extract_constant_name(node.cpath)
37
+ full_name = (namespace + [class_name]).join('::')
38
+ methods = extract_methods(node.body)
39
+
40
+ classes << {
41
+ name: full_name,
42
+ simple_name: class_name,
43
+ methods: methods
44
+ }
45
+
46
+ # Also look for nested classes within this class
47
+ new_namespace = namespace + [class_name]
48
+ classes.concat(extract_classes(node.body, new_namespace)) if node.respond_to?(:body)
49
+
50
+ when Kanayago::ScopeNode
51
+ classes.concat(extract_classes(node.body, namespace)) if node.respond_to?(:body)
52
+
53
+ when Kanayago::BlockNode
54
+ # BlockNode is an Array, iterate through its elements
55
+ node.each do |child|
56
+ classes.concat(extract_classes(child, namespace))
57
+ end
58
+ end
59
+
60
+ classes
61
+ end
62
+ # rubocop:enable Metrics/CyclomaticComplexity
63
+
64
+ def extract_constant_name(node)
65
+ case node
66
+ when Kanayago::Colon2Node
67
+ # Extract the class name from mid (Symbol)
68
+ node.mid.to_s
69
+ else
70
+ 'UnknownClass'
71
+ end
72
+ end
73
+
74
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
75
+ def extract_methods(node, visibility = :public)
76
+ methods = []
77
+ current_visibility = visibility
78
+
79
+ return methods unless node
80
+
81
+ case node
82
+ when Kanayago::DefinitionNode
83
+ method_info = {
84
+ name: node.mid.to_s,
85
+ visibility: current_visibility,
86
+ parameters: extract_parameters(node)
87
+ }
88
+ methods << method_info if current_visibility == :public
89
+
90
+ when Kanayago::ScopeNode
91
+ # ScopeNode contains body, process it recursively
92
+ methods.concat(extract_methods(node.body, current_visibility)) if node.respond_to?(:body)
93
+
94
+ when Kanayago::BlockNode
95
+ # BlockNode is an Array, iterate through its elements
96
+ node.each do |child|
97
+ # Check if this is a visibility modifier
98
+ if child.is_a?(Kanayago::VariableCallNode) && child.respond_to?(:mid)
99
+ case child.mid.to_s
100
+ when 'private'
101
+ current_visibility = :private
102
+ when 'protected'
103
+ current_visibility = :protected
104
+ when 'public'
105
+ current_visibility = :public
106
+ end
107
+ else
108
+ # Process other nodes (including DefinitionNodes)
109
+ methods.concat(extract_methods(child, current_visibility))
110
+ end
111
+ end
112
+ end
113
+
114
+ methods
115
+ end
116
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
117
+
118
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
119
+ def extract_parameters(def_node)
120
+ params = []
121
+ return params unless def_node.respond_to?(:defn)
122
+
123
+ defn = def_node.defn
124
+ return params unless defn.respond_to?(:args)
125
+
126
+ args = defn.args
127
+ return params unless args.respond_to?(:ainfo)
128
+
129
+ ainfo = args.ainfo
130
+ return params unless ainfo.is_a?(Hash)
131
+
132
+ # Handle required positional parameters (pre_args)
133
+ pre_count = ainfo[:pre_args_num] || 0
134
+ pre_count.times do |i|
135
+ params << {
136
+ name: "arg#{i + 1}",
137
+ type: :required
138
+ }
139
+ end
140
+
141
+ # Handle optional parameters
142
+ if ainfo[:opt_args]
143
+ current_opt = ainfo[:opt_args]
144
+ while current_opt
145
+ if current_opt.respond_to?(:body) && current_opt.body.respond_to?(:id)
146
+ params << {
147
+ name: current_opt.body.id.to_s,
148
+ type: :optional
149
+ }
150
+ end
151
+ current_opt = current_opt.respond_to?(:next) ? current_opt.next : nil
152
+ end
153
+ end
154
+
155
+ # Handle keyword parameters
156
+ if ainfo[:kw_args]
157
+ current_kw = ainfo[:kw_args]
158
+ while current_kw
159
+ if current_kw.respond_to?(:body) && current_kw.body.respond_to?(:id)
160
+ params << {
161
+ name: current_kw.body.id.to_s,
162
+ type: :keyword
163
+ }
164
+ end
165
+ current_kw = current_kw.respond_to?(:next) ? current_kw.next : nil
166
+ end
167
+ end
168
+
169
+ params
170
+ end
171
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
172
+
173
+ def generate_rspec(class_info)
174
+ output = []
175
+ output << "require 'spec_helper'"
176
+ output << ''
177
+ output << "RSpec.describe #{class_info[:name]} do"
178
+
179
+ if class_info[:methods].empty?
180
+ output << ' # No public methods found'
181
+ else
182
+ class_info[:methods].each do |method|
183
+ output << generate_method_spec(method)
184
+ end
185
+ end
186
+
187
+ output << 'end'
188
+ output.join("\n")
189
+ end
190
+
191
+ def generate_method_spec(method)
192
+ lines = []
193
+ method_name = method[:name]
194
+ params = method[:parameters]
195
+
196
+ lines << " describe '##{method_name}' do"
197
+
198
+ if method_name.end_with?('?')
199
+ # Boolean methods - generate true/false cases
200
+ lines << " context 'when condition is met' do"
201
+ lines << " it 'returns true' do"
202
+ lines << ' # TODO: implement'
203
+ lines << ' end'
204
+ lines << ' end'
205
+ lines << ''
206
+ lines << " context 'when condition is not met' do"
207
+ lines << " it 'returns false' do"
208
+ lines << ' # TODO: implement'
209
+ lines << ' end'
210
+ lines << ' end'
211
+ elsif method_name == 'initialize'
212
+ # Constructor - check for optional parameters
213
+ lines << " it 'creates a new instance' do"
214
+ lines << ' # TODO: implement'
215
+ lines << ' end'
216
+
217
+ if params.any? { |p| %i[optional keyword].include?(p[:type]) }
218
+ lines << ''
219
+ lines << " it 'uses default values when optional parameters are not provided' do"
220
+ lines << ' # TODO: implement'
221
+ lines << ' end'
222
+ end
223
+ else
224
+ # Regular methods
225
+ lines << " it 'works correctly' do"
226
+ lines << ' # TODO: implement'
227
+ lines << ' end'
228
+
229
+ if params.any? { |p| %i[optional keyword].include?(p[:type]) }
230
+ lines << ''
231
+ lines << " context 'with optional parameters' do"
232
+ lines << " it 'handles optional parameters' do"
233
+ lines << ' # TODO: implement'
234
+ lines << ' end'
235
+ lines << ' end'
236
+ end
237
+ end
238
+
239
+ lines << ' end'
240
+ lines << ''
241
+ lines.join("\n")
242
+ end
243
+ end
244
+
245
+ # Usage example
246
+ sample_code = <<~RUBY
247
+ class User
248
+ class Profile
249
+ def initialize(name, age = 20)
250
+ @name = name
251
+ @age = age
252
+ end
253
+
254
+ def adult?
255
+ @age >= 18
256
+ end
257
+
258
+ def greet(message = "Hello")
259
+ "\#{message}, \#{@name}!"
260
+ end
261
+
262
+ private
263
+
264
+ def internal_method
265
+ # This should not appear in tests
266
+ end
267
+ end
268
+ end
269
+ RUBY
270
+
271
+ generator = TestGenerator.new(sample_code)
272
+ puts generator.generate
@@ -0,0 +1,9 @@
1
+ {
2
+ "typeprof_version": "experimental",
3
+ "rbs_dir": "sig/",
4
+ "analysis_unit_dirs": [
5
+ "lib/",
6
+ "lib/kanayago/"
7
+ ],
8
+ "diagnostic_severity": "error"
9
+ }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kanayago
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - S-H-GAMELINKS
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2024-09-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Trying to Make Ruby's Parser Available as a Gem
13
13
  email:
@@ -19,6 +19,7 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - ".rubocop.yml"
21
21
  - ".rubocop_todo.yml"
22
+ - ".ruby-version"
22
23
  - LICENSE.txt
23
24
  - README.md
24
25
  - Rakefile
@@ -30,6 +31,7 @@ files:
30
31
  - ext/kanayago/extconf.rb
31
32
  - ext/kanayago/id.h
32
33
  - ext/kanayago/id_table.h
34
+ - ext/kanayago/include/ruby/st.h
33
35
  - ext/kanayago/internal.h
34
36
  - ext/kanayago/internal/array.h
35
37
  - ext/kanayago/internal/basic_operators.h
@@ -45,6 +47,7 @@ files:
45
47
  - ext/kanayago/internal/hash.h
46
48
  - ext/kanayago/internal/imemo.h
47
49
  - ext/kanayago/internal/io.h
50
+ - ext/kanayago/internal/namespace.h
48
51
  - ext/kanayago/internal/numeric.h
49
52
  - ext/kanayago/internal/parse.h
50
53
  - ext/kanayago/internal/rational.h
@@ -52,6 +55,7 @@ files:
52
55
  - ext/kanayago/internal/ruby_parser.h
53
56
  - ext/kanayago/internal/sanitizers.h
54
57
  - ext/kanayago/internal/serial.h
58
+ - ext/kanayago/internal/set_table.h
55
59
  - ext/kanayago/internal/static_assert.h
56
60
  - ext/kanayago/internal/string.h
57
61
  - ext/kanayago/internal/symbol.h
@@ -62,33 +66,56 @@ files:
62
66
  - ext/kanayago/kanayago.c
63
67
  - ext/kanayago/kanayago.h
64
68
  - ext/kanayago/lex.c
69
+ - ext/kanayago/literal_node.c
70
+ - ext/kanayago/literal_node.h
65
71
  - ext/kanayago/method.h
66
72
  - ext/kanayago/node.c
67
73
  - ext/kanayago/node.h
68
74
  - ext/kanayago/node_name.inc
69
75
  - ext/kanayago/parse.c
70
76
  - ext/kanayago/parse.h
71
- - ext/kanayago/parse.tmp.y
72
77
  - ext/kanayago/parser_bits.h
73
78
  - ext/kanayago/parser_node.h
74
79
  - ext/kanayago/parser_st.c
75
80
  - ext/kanayago/parser_st.h
76
81
  - ext/kanayago/parser_value.h
82
+ - ext/kanayago/pattern_node.c
83
+ - ext/kanayago/pattern_node.h
77
84
  - ext/kanayago/probes.h
78
85
  - ext/kanayago/ruby_assert.h
79
86
  - ext/kanayago/ruby_atomic.h
80
87
  - ext/kanayago/ruby_parser.c
81
88
  - ext/kanayago/rubyparser.h
89
+ - ext/kanayago/scope_node.c
90
+ - ext/kanayago/scope_node.h
82
91
  - ext/kanayago/shape.h
83
92
  - ext/kanayago/st.c
93
+ - ext/kanayago/statement_node.c
94
+ - ext/kanayago/statement_node.h
95
+ - ext/kanayago/string_node.c
96
+ - ext/kanayago/string_node.h
84
97
  - ext/kanayago/symbol.h
85
98
  - ext/kanayago/thread_pthread.h
86
99
  - ext/kanayago/universal_parser.c
100
+ - ext/kanayago/variable_node.c
101
+ - ext/kanayago/variable_node.h
87
102
  - ext/kanayago/vm_core.h
88
103
  - ext/kanayago/vm_opts.h
89
104
  - lib/kanayago.rb
105
+ - lib/kanayago/literal_node.rb
106
+ - lib/kanayago/pattern_node.rb
107
+ - lib/kanayago/statement_node.rb
108
+ - lib/kanayago/string_node.rb
109
+ - lib/kanayago/variable_node.rb
90
110
  - lib/kanayago/version.rb
111
+ - patch/3.4/copy_target.rb
112
+ - patch/3.4/kanayago.patch
113
+ - patch/head/copy_target.rb
114
+ - patch/head/kanayago.patch
115
+ - sample/minitest_generator.rb
116
+ - sample/test_generator.rb
91
117
  - sig/kanayago.rbs
118
+ - typeprof.conf.json
92
119
  homepage: https://github.com/S-H-GAMELINKS/kanayago
93
120
  licenses:
94
121
  - MIT
@@ -96,6 +123,7 @@ metadata:
96
123
  homepage_uri: https://github.com/S-H-GAMELINKS/kanayago
97
124
  source_code_uri: https://github.com/S-H-GAMELINKS/kanayago
98
125
  changelog_uri: https://github.com/S-H-GAMELINKS/kanayago/releases
126
+ rubygems_mfa_required: 'true'
99
127
  rdoc_options: []
100
128
  require_paths:
101
129
  - lib
@@ -110,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
138
  - !ruby/object:Gem::Version
111
139
  version: '0'
112
140
  requirements: []
113
- rubygems_version: 3.6.0.dev
141
+ rubygems_version: 3.8.0.dev
114
142
  specification_version: 4
115
143
  summary: Trying to Make Ruby's Parser Available as a Gem
116
144
  test_files: []