gloss 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +3 -0
  3. data/.github/workflows/{crystal.yml → crystal_specs.yml} +1 -1
  4. data/.github/workflows/{ruby.yml → ruby_specs.yml} +1 -1
  5. data/.gloss.yml +1 -0
  6. data/.rspec +1 -0
  7. data/Gemfile.lock +25 -27
  8. data/README.md +36 -5
  9. data/exe/gloss +13 -2
  10. data/ext/gloss/{src/lib → lib}/cr_ruby.cr +0 -0
  11. data/ext/gloss/lib/rbs_types.cr +3 -0
  12. data/ext/gloss/spec/parser_spec.cr +83 -50
  13. data/ext/gloss/src/cr_ast.cr +146 -72
  14. data/ext/gloss/src/gloss.cr +2 -2
  15. data/ext/gloss/src/lexer.cr +59 -1
  16. data/ext/gloss/src/parser.cr +4 -4
  17. data/ext/gloss/src/rb_ast.cr +152 -57
  18. data/lib/gloss.rb +15 -7
  19. data/lib/gloss/cli.rb +85 -27
  20. data/lib/gloss/config.rb +18 -10
  21. data/lib/gloss/errors.rb +13 -7
  22. data/lib/gloss/initializer.rb +11 -6
  23. data/lib/gloss/logger.rb +29 -0
  24. data/lib/gloss/parser.rb +22 -5
  25. data/lib/gloss/prog_loader.rb +141 -0
  26. data/lib/gloss/scope.rb +7 -2
  27. data/lib/gloss/source.rb +17 -14
  28. data/lib/gloss/type_checker.rb +105 -66
  29. data/lib/gloss/utils.rb +44 -0
  30. data/lib/gloss/version.rb +6 -1
  31. data/lib/gloss/visitor.rb +667 -0
  32. data/lib/gloss/watcher.rb +63 -19
  33. data/lib/gloss/writer.rb +35 -18
  34. data/sig/core.rbs +2 -0
  35. data/sig/fast_blank.rbs +4 -0
  36. data/sig/gls.rbs +3 -0
  37. data/sig/listen.rbs +1 -0
  38. data/sig/optparse.rbs +6 -0
  39. data/sig/rubygems.rbs +9 -0
  40. data/sig/yaml.rbs +3 -0
  41. data/src/exe/gloss +19 -0
  42. data/src/lib/gloss.gl +26 -0
  43. data/src/lib/gloss/cli.gl +70 -0
  44. data/src/lib/gloss/config.gl +21 -0
  45. data/src/lib/gloss/errors.gl +11 -0
  46. data/src/lib/gloss/initializer.gl +20 -0
  47. data/src/lib/gloss/logger.gl +21 -0
  48. data/src/lib/gloss/parser.gl +31 -0
  49. data/src/lib/gloss/prog_loader.gl +133 -0
  50. data/src/lib/gloss/scope.gl +7 -0
  51. data/src/lib/gloss/source.gl +32 -0
  52. data/src/lib/gloss/type_checker.gl +119 -0
  53. data/src/lib/gloss/utils.gl +38 -0
  54. data/src/lib/gloss/version.gl +3 -0
  55. data/src/lib/gloss/visitor.gl +575 -0
  56. data/src/lib/gloss/watcher.gl +66 -0
  57. data/src/lib/gloss/writer.gl +35 -0
  58. metadata +35 -8
  59. data/lib/gloss/builder.rb +0 -393
  60. data/src/lib/hrb/initializer.gl +0 -22
  61. data/src/lib/hrb/watcher.gl +0 -32
@@ -1,4 +1,5 @@
1
- require "./lib/cr_ruby"
1
+ require "../lib/cr_ruby"
2
+ require "../lib/rbs_types"
2
3
  require "./cr_ast"
3
4
  require "./rb_ast"
4
5
  require "./parser"
@@ -10,7 +11,6 @@ def parse_string(self : CrRuby::VALUE, str : CrRuby::VALUE)
10
11
  output = begin
11
12
  Gloss.parse_string(string)
12
13
  rescue e : Crystal::SyntaxException
13
- pp e.backtrace
14
14
  e.to_s
15
15
  end
16
16
 
@@ -115,7 +115,7 @@ module Crystal
115
115
  case next_char
116
116
  when '='
117
117
  next_char :"<<="
118
- when '-'
118
+ when '-', '~'
119
119
  has_single_quote = false
120
120
  found_closing_single_quote = false
121
121
 
@@ -1182,5 +1182,63 @@ module Crystal
1182
1182
 
1183
1183
  @token
1184
1184
  end
1185
+
1186
+ def check_heredoc_start
1187
+ return nil unless current_char == '<' && next_char == '<' && {'-', '~'}.includes?(next_char)
1188
+
1189
+ has_single_quote = false
1190
+ found_closing_single_quote = false
1191
+
1192
+ char = next_char
1193
+ start_here = current_pos
1194
+
1195
+ if char == '\''
1196
+ has_single_quote = true
1197
+ char = next_char
1198
+ start_here = current_pos
1199
+ end
1200
+
1201
+ return nil unless ident_part?(char)
1202
+
1203
+ end_here = 0
1204
+
1205
+ while true
1206
+ char = next_char
1207
+ case
1208
+ when char == '\r'
1209
+ if peek_next_char == '\n'
1210
+ end_here = current_pos
1211
+ next_char
1212
+ break
1213
+ else
1214
+ return nil
1215
+ end
1216
+ when char == '\n'
1217
+ end_here = current_pos
1218
+ break
1219
+ when ident_part?(char)
1220
+ # ok
1221
+ when char == '\0'
1222
+ return nil
1223
+ else
1224
+ if char == '\'' && has_single_quote
1225
+ found_closing_single_quote = true
1226
+ end_here = current_pos
1227
+ next_char
1228
+ break
1229
+ elsif has_single_quote
1230
+ # wait until another quote
1231
+ else
1232
+ end_here = current_pos
1233
+ break
1234
+ end
1235
+ end
1236
+ end
1237
+
1238
+ return nil if has_single_quote && !found_closing_single_quote
1239
+
1240
+ here = string_range(start_here, end_here)
1241
+ Token::DelimiterState.new(:heredoc, here, here, allow_escapes: !has_single_quote)
1242
+ end
1185
1243
  end
1186
1244
  end
@@ -17,10 +17,10 @@ module Gloss
17
17
  line = @line_number
18
18
  column = @token.column_number
19
19
 
20
- # next_token_skip_space
21
- # next_token_skip_space_or_newline
22
- # of = nil
23
- Crystal::ArrayLiteral.new([] of Crystal::ASTNode) # .at_end(of)
20
+ next_token_skip_space
21
+ next_token_skip_space_or_newline
22
+ of = nil
23
+ Crystal::ArrayLiteral.new([] of Crystal::ASTNode).at_end(of)
24
24
  end
25
25
 
26
26
  def new_hash_literal(entries, line, column, end_location, allow_of = true)
@@ -19,7 +19,7 @@ module Rb
19
19
  abstract class NodeWithChildren < Node
20
20
  @info : NamedTuple(type: String, children: Array(Node))
21
21
 
22
- def initialize(@children : Array(Node))
22
+ def initialize(@children : Array(Node), location : Crystal::Location?)
23
23
  @info = {
24
24
  type: self.class.name.split("::").last,
25
25
  children: @children,
@@ -32,7 +32,7 @@ module Rb
32
32
  abstract class NodeWithValue < Node
33
33
  @info : NamedTuple(type: String, value: String)
34
34
 
35
- def initialize(@value : String)
35
+ def initialize(@value : String, location : Crystal::Location?)
36
36
  @info = {
37
37
  type: self.class.name.split("::").last,
38
38
  value: @value,
@@ -43,13 +43,14 @@ module Rb
43
43
  end
44
44
 
45
45
  class Block < Node
46
- @info : NamedTuple(type: String, args: Array(Var), body: Node)
46
+ @info : NamedTuple(type: String, positional_args: Array(Var), body: Node, rest_p_args: Node?)
47
47
 
48
- def initialize(args, body)
48
+ def initialize(args, splat, body, location : Crystal::Location?)
49
49
  @info = {
50
50
  type: self.class.name.split("::").last,
51
51
  body: body,
52
- args: args,
52
+ positional_args: args,
53
+ rest_p_args: splat
53
54
  }
54
55
  end
55
56
 
@@ -62,7 +63,7 @@ module Rb
62
63
  class ClassNode < Node
63
64
  @info : NamedTuple(type: String, name: Path, body: Node, superclass: Node?, type_vars: Array(String)?, abstract: Bool)
64
65
 
65
- def initialize(name : Path, body : Node, superclass : Node?, type_vars : Array(String)?, abstr : Bool)
66
+ def initialize(name : Path, body : Node, superclass : Node?, type_vars : Array(String)?, abstr : Bool, location : Crystal::Location?)
66
67
  @info = {
67
68
  type: self.class.name.split("::").last,
68
69
  name: name,
@@ -80,7 +81,7 @@ module Rb
80
81
  class ModuleNode < Node
81
82
  @info : NamedTuple(type: String, name: Path, body: Node, type_vars: Array(String)?)
82
83
 
83
- def initialize(name : Path, body : Node, type_vars : Array(String)?)
84
+ def initialize(name : Path, body : Node, type_vars : Array(String)?, location : Crystal::Location?)
84
85
  @info = {
85
86
  type: self.class.name.split("::").last,
86
87
  name: name,
@@ -94,18 +95,32 @@ module Rb
94
95
  end
95
96
 
96
97
  class DefNode < Node
97
- @info : NamedTuple(type: String, name: String, body: Node, rp_args: Array(Arg), receiver: Node?,
98
- return_type: Node?, rest_kw_args: Arg?)
99
-
100
- def initialize(name : String, rp_args : Array(Arg), body : Node, receiver : Node?, return_type : Node?, rest_kw_args)
98
+ @info : NamedTuple(type: String, name: String, body: Node, positional_args: Array(Arg), receiver: Node?,
99
+ return_type: Node?, rest_kw_args: Arg?, rest_p_args: Arg?, block_arg: Node?, yield_arg_count: Int32?)
100
+
101
+ def initialize(
102
+ receiver : Node?,
103
+ name : String,
104
+ positional_args : Array(Arg),
105
+ splat,
106
+ rest_kw_args,
107
+ body : Node,
108
+ return_type : Node?,
109
+ yields : Int32?,
110
+ block_arg : Node?,
111
+ location : Crystal::Location?
112
+ )
101
113
  @info = {
102
- type: self.class.name.split("::").last,
103
- name: name,
104
- body: body,
105
- rp_args: rp_args,
106
- rest_kw_args: rest_kw_args,
107
- receiver: receiver,
108
- return_type: return_type,
114
+ type: self.class.name.split("::").last,
115
+ name: name,
116
+ body: body,
117
+ positional_args: positional_args,
118
+ rest_kw_args: rest_kw_args,
119
+ receiver: receiver,
120
+ return_type: return_type,
121
+ rest_p_args: splat,
122
+ yield_arg_count: yields,
123
+ block_arg: block_arg
109
124
  }
110
125
  end
111
126
 
@@ -113,18 +128,18 @@ module Rb
113
128
  end
114
129
 
115
130
  class Arg < Node
116
- @info : NamedTuple(type: String, name: String, external_name: String, default_value: Node?,
131
+ @info : NamedTuple(type: String, name: String, external_name: String, value: Node?,
117
132
  restriction: Node?, keyword_arg: Bool)
118
133
 
119
- def initialize(name : String, external_name : String, restriction : Node?, default_value :
120
- Node?, keyword_arg)
134
+ def initialize(name : String, external_name : String, restriction : Node?, value : Node?,
135
+ keyword_arg, location : Crystal::Location?)
121
136
  @info = {
122
137
  type: self.class.name.split("::").last,
123
138
  name: name,
124
139
  restriction: restriction,
125
- default_value: default_value,
140
+ value: value,
126
141
  external_name: external_name,
127
- keyword_arg: keyword_arg
142
+ keyword_arg: keyword_arg,
128
143
  }
129
144
  end
130
145
 
@@ -134,7 +149,7 @@ module Rb
134
149
  class LiteralNode < Node
135
150
  @info : NamedTuple(type: String, value: String | Int32 | Bool | Nil, rb_type: String)
136
151
 
137
- def initialize(value, rb_type : RbLiteral)
152
+ def initialize(value, rb_type : RbLiteral, location : Crystal::Location?)
138
153
  val = case rb_type
139
154
  when Rb::AST::RbLiteral::TrueClass
140
155
  true
@@ -160,7 +175,7 @@ module Rb
160
175
  class ArrayLiteral < Node
161
176
  @info : NamedTuple(type: String, elements: Array(Node), frozen: Bool)
162
177
 
163
- def initialize(elems, frozen = false)
178
+ def initialize(elems, location : Crystal::Location?, frozen = false)
164
179
  @info = {
165
180
  type: self.class.name.split("::").last,
166
181
  elements: elems,
@@ -174,7 +189,7 @@ module Rb
174
189
  class HashLiteral < Node
175
190
  @info : NamedTuple(type: String, elements: Array(Tuple(Node, Node)) | Array(Tuple(String, Node)), frozen: Bool)
176
191
 
177
- def initialize(elems, frozen = false)
192
+ def initialize(elems, location : Crystal::Location?, frozen = false)
178
193
  @info = {
179
194
  type: self.class.name.split("::").last,
180
195
  elements: elems,
@@ -188,7 +203,7 @@ module Rb
188
203
  class RangeLiteral < Node
189
204
  @info : NamedTuple(type: String, from: Node, to: Node, exclusive: Bool)
190
205
 
191
- def initialize(from, to, exclusive)
206
+ def initialize(from, to, exclusive, location : Crystal::Location?)
192
207
  @info = {
193
208
  type: self.class.name.split("::").last,
194
209
  from: from,
@@ -200,7 +215,17 @@ module Rb
200
215
  delegate :to_json, to: @info
201
216
  end
202
217
 
203
- class RegexLiteral < NodeWithValue
218
+ class RegexLiteral < Node
219
+ @info : NamedTuple(type: String, value: Node)
220
+
221
+ def initialize(value, location : Crystal::Location?)
222
+ @info = {
223
+ type: self.class.name.split("::").last,
224
+ value: value,
225
+ }
226
+ end
227
+
228
+ delegate :to_json, to: @info
204
229
  end
205
230
 
206
231
  class Nop < Node
@@ -214,7 +239,7 @@ module Rb
214
239
  end
215
240
 
216
241
  class EmptyNode < Nop
217
- def initialize(class_name : String)
242
+ def initialize(class_name : String, location : Crystal::Location?)
218
243
  STDERR.puts "Encountered a ruby EmptyNode class name: #{class_name}"
219
244
  @info = {
220
245
  type: self.class.name.split("::").last,
@@ -225,7 +250,7 @@ module Rb
225
250
  class Var < Node
226
251
  @info : NamedTuple(type: String, name: String)
227
252
 
228
- def initialize(@name : String)
253
+ def initialize(@name : String, location : Crystal::Location?)
229
254
  @info = {
230
255
  type: self.class.name.split("::").last,
231
256
  name: @name,
@@ -244,7 +269,7 @@ module Rb
244
269
  abstract class Conditional < Node
245
270
  @info : NamedTuple(type: String, condition: Node, then: Node, else: Node)
246
271
 
247
- def initialize(@condition : Node, @thn : Node, @els : Node)
272
+ def initialize(@condition : Node, @thn : Node, @els : Node, location : Crystal::Location?)
248
273
  @info = {
249
274
  type: self.class.name.split("::").last,
250
275
  condition: @condition,
@@ -265,7 +290,7 @@ module Rb
265
290
  class Case < Node
266
291
  @info : NamedTuple(type: String, condition: Node?, whens: Array(When), else: Node?, exhaustive: Bool)
267
292
 
268
- def initialize(cond : Node?, whens : Array(When), els : Node?, exhaustive : Bool)
293
+ def initialize(cond : Node?, whens : Array(When), els : Node?, exhaustive : Bool, location : Crystal::Location?)
269
294
  @info = {
270
295
  type: self.class.name.split("::").last,
271
296
  condition: cond,
@@ -281,7 +306,7 @@ module Rb
281
306
  class When < Node
282
307
  @info : NamedTuple(type: String, conditions: Array(Node), body: Node, exhaustive: Bool)
283
308
 
284
- def initialize(conds : Array(Node), body : Node, exhaustive : Bool)
309
+ def initialize(conds : Array(Node), body : Node, exhaustive : Bool, location : Crystal::Location?)
285
310
  @info = {
286
311
  type: self.class.name.split("::").last,
287
312
  conditions: conds,
@@ -296,7 +321,7 @@ module Rb
296
321
  class Enum < Node
297
322
  @info : NamedTuple(type: String, name: Crystal::Path, members: Array(Node))
298
323
 
299
- def initialize(@name : Crystal::Path, @members : Array(Node))
324
+ def initialize(@name : Crystal::Path, @members : Array(Node), location : Crystal::Location?)
300
325
  @info = {
301
326
  type: self.class.name.split("::").last,
302
327
  name: @name,
@@ -308,16 +333,18 @@ module Rb
308
333
  end
309
334
 
310
335
  class Call < Node
311
- @info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block: Block?, block_arg: Node?)
336
+ @info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block: Block?, block_arg: Node?, named_args: Array(Arg)?, has_parentheses: Bool)
312
337
 
313
- def initialize(object : Node?, name : String, args : Array(Node), block, block_arg)
338
+ def initialize(object : Node?, name : String, args : Array(Node), named_args, block, block_arg, has_parentheses, location : Crystal::Location?)
314
339
  @info = {
315
- type: self.class.name.split("::").last,
316
- name: name,
317
- args: args,
318
- object: object,
319
- block: block,
320
- block_arg: block_arg,
340
+ type: self.class.name.split("::").last,
341
+ name: name,
342
+ args: args,
343
+ object: object,
344
+ block: block,
345
+ block_arg: block_arg,
346
+ named_args: named_args,
347
+ has_parentheses: has_parentheses || false,
321
348
  }
322
349
  end
323
350
 
@@ -333,7 +360,7 @@ module Rb
333
360
  class StringInterpolation < Node
334
361
  @info : NamedTuple(type: String, contents: Array(Node))
335
362
 
336
- def initialize(contents)
363
+ def initialize(contents, location : Crystal::Location?)
337
364
  @info = {
338
365
  type: self.class.name.split("::").last,
339
366
  contents: contents,
@@ -346,7 +373,7 @@ module Rb
346
373
  class UnaryExpr < Node
347
374
  @info : NamedTuple(type: String, op: String, value: Node, with_parens: Bool)
348
375
 
349
- def initialize(val, op, parens)
376
+ def initialize(val, op, parens, location : Crystal::Location?)
350
377
  @info = {
351
378
  type: self.class.name.split("::").last,
352
379
  value: val,
@@ -361,7 +388,7 @@ module Rb
361
388
  class BinaryOp < Node
362
389
  @info : NamedTuple(type: String, op: String, left: Node, right: Node)
363
390
 
364
- def initialize(op, left, right)
391
+ def initialize(op, left, right, location : Crystal::Location?)
365
392
  @info = {
366
393
  type: self.class.name.split("::").last,
367
394
  left: left,
@@ -376,7 +403,7 @@ module Rb
376
403
  class Assign < Node
377
404
  @info : NamedTuple(type: String, op: String?, target: Node, value: Node)
378
405
 
379
- def initialize(target, value, op = nil)
406
+ def initialize(target, value, op, location : Crystal::Location?)
380
407
  @info = {
381
408
  type: self.class.name.split("::").last,
382
409
  target: target,
@@ -388,10 +415,24 @@ module Rb
388
415
  delegate :to_json, to: @info
389
416
  end
390
417
 
418
+ class MultiAssign < Node
419
+ @info : NamedTuple(type: String, targets: Array(Node), values: Array(Node))
420
+
421
+ def initialize(targets, values, location : Crystal::Location?)
422
+ @info = {
423
+ type: self.class.name.split("::").last,
424
+ targets: targets,
425
+ values: values,
426
+ }
427
+ end
428
+
429
+ delegate :to_json, to: @info
430
+ end
431
+
391
432
  class TypeDeclaration < Node
392
433
  @info : NamedTuple(type: String, var: Node, declared_type: Node, value: Node?, var_type: String)
393
434
 
394
- def initialize(@var : Node, @declared_type : Node, @value : Node?)
435
+ def initialize(@var : Node, @declared_type : Node, @value : Node?, location : Crystal::Location?)
395
436
  @info = {
396
437
  type: self.class.name.split("::").last,
397
438
  var: @var,
@@ -407,7 +448,7 @@ module Rb
407
448
  class MacroFor < Node
408
449
  @info : NamedTuple(type: String, vars: Array(Var), expr: Node, body: Node)
409
450
 
410
- def initialize(vars, expr, body)
451
+ def initialize(vars, expr, body, location : Crystal::Location?)
411
452
  @info = {
412
453
  type: self.class.name.split("::").last,
413
454
  vars: vars,
@@ -428,7 +469,7 @@ module Rb
428
469
  class MacroExpression < Node
429
470
  @info : NamedTuple(type: String, expr: Node, output: Bool)
430
471
 
431
- def initialize(expr, output)
472
+ def initialize(expr, output, location : Crystal::Location?)
432
473
  @info = {
433
474
  type: self.class.name.split("::").last,
434
475
  expr: expr,
@@ -442,7 +483,7 @@ module Rb
442
483
  class ControlExpression < Node
443
484
  @info : NamedTuple(type: String, value: Node?)
444
485
 
445
- def initialize(value)
486
+ def initialize(value, location : Crystal::Location?)
446
487
  @info = {
447
488
  type: self.class.name.split("::").last,
448
489
  value: value,
@@ -465,7 +506,7 @@ module Rb
465
506
  @info : NamedTuple(type: String, body: Node, rescues: Array(Rescue)?, else: Node?,
466
507
  ensure: Node?)
467
508
 
468
- def initialize(body, rescues, else_node, ensure_node)
509
+ def initialize(body, rescues, else_node, ensure_node, location : Crystal::Location?)
469
510
  @info = {
470
511
  type: self.class.name.split("::").last,
471
512
  body: body,
@@ -481,7 +522,7 @@ module Rb
481
522
  class Rescue < Node
482
523
  @info : NamedTuple(type: String, body: Node, types: Array(Node)?, name: String?)
483
524
 
484
- def initialize(body, types, name)
525
+ def initialize(body, types, name, location : Crystal::Location?)
485
526
  @info = {
486
527
  type: self.class.name.split("::").last,
487
528
  body: body,
@@ -496,10 +537,10 @@ module Rb
496
537
  class Union < Node
497
538
  @info : NamedTuple(type: String, types: Array(Node))
498
539
 
499
- def initialize(types)
540
+ def initialize(types, location : Crystal::Location?)
500
541
  @info = {
501
542
  type: self.class.name.split("::").last,
502
- types: types
543
+ types: types,
503
544
  }
504
545
  end
505
546
 
@@ -509,11 +550,65 @@ module Rb
509
550
  class Generic < Node
510
551
  @info : NamedTuple(type: String, name: Node, args: Array(Node))
511
552
 
512
- def initialize(name, args)
553
+ def initialize(name, args, location : Crystal::Location?)
513
554
  @info = {
514
- type: self.class.name.split("::").last,
555
+ type: self.class.name.split("::").last,
556
+ name: name,
557
+ args: args,
558
+ }
559
+ end
560
+
561
+ delegate :to_json, to: @info
562
+ end
563
+
564
+ class Proc < Node
565
+ @info : NamedTuple(type: String, function: DefNode)
566
+
567
+ def initialize(function, location : Crystal::Location?)
568
+ @info = {
569
+ type: self.class.name.split("::").last,
570
+ function: function,
571
+ }
572
+ end
573
+
574
+ delegate :to_json, to: @info
575
+ end
576
+
577
+ class NodeWithNameNode < Node
578
+ @info : NamedTuple(type: String, name: Node)
579
+
580
+ def initialize(name, location : Crystal::Location?)
581
+ @info = {
582
+ type: self.class.name.split("::").last,
515
583
  name: name,
516
- args: args
584
+ }
585
+ end
586
+
587
+ delegate :to_json, to: @info
588
+ end
589
+
590
+ class Extend < NodeWithNameNode
591
+ end
592
+
593
+ class Include < NodeWithNameNode
594
+ end
595
+
596
+ class VisibilityModifier < Node
597
+ @info : NamedTuple(type: String, visibility: String, exp: Node)
598
+
599
+ def initialize(visibility : Crystal::Visibility, exp : Node, location : Crystal::Location?)
600
+ vis = case visibility
601
+ when Crystal::Visibility::Public
602
+ "public"
603
+ when Crystal::Visibility::Protected
604
+ "protected"
605
+ when Crystal::Visibility::Private
606
+ "private"
607
+ end
608
+ @info = {
609
+ type: self.class.name.split("::").last,
610
+ visibility: vis.as(String),
611
+ exp: exp,
517
612
  }
518
613
  end
519
614