katakata_irb 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +8 -2
- data/README.md +16 -26
- data/bin/console +2 -7
- data/katakata_irb.gemspec +2 -1
- data/lib/katakata_irb/completor.rb +45 -6
- data/lib/katakata_irb/{trex.rb → nesting_parser.rb} +54 -32
- data/lib/katakata_irb/type_simulator.rb +25 -11
- data/lib/katakata_irb/types.rb +15 -18
- data/lib/katakata_irb/version.rb +1 -1
- data/lib/katakata_irb.rb +5 -7
- metadata +20 -16
- data/exe/kirb +0 -11
- data/lib/katakata_irb/reline_patch.rb +0 -43
- data/lib/katakata_irb/reline_patches/escapeseq.patch +0 -45
- data/lib/katakata_irb/reline_patches/fullwidth.patch +0 -200
- data/lib/katakata_irb/reline_patches/indent.patch +0 -25
- data/lib/katakata_irb/reline_patches/raw.patch +0 -95
- data/lib/katakata_irb/reline_patches/scrollbar.patch +0 -43
- data/lib/katakata_irb/reline_patches/wholelines.patch +0 -102
- data/lib/katakata_irb/ruby_lex_patch.rb +0 -216
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e13d1b43d98e8be7595125b4e1e27533d83da1ee4d87df0dfb613d8fb8adee4
|
4
|
+
data.tar.gz: ae508bc65cd1049100fe4811b1d2b27036b30131cab13821d52b637e91e2ed41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be9ed49c8de27772f7ec154df136134e9d5319a851fe392656a67d3c49069ed040a41b2af8deb6e81577c0c59c6d5bc0918a8165e09ccab2bce15fd6f09abba8
|
7
|
+
data.tar.gz: 8d9554e6532488742e156d39e7ee63c3c2461900db42badfd0d49990e35769b1e0f34a8cd746d5aab57839d3f31e894a081ec42389cd2383dafab5043d3fa578
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
katakata_irb (0.1.
|
4
|
+
katakata_irb (0.1.4)
|
5
|
+
irb (>= 1.4.0)
|
5
6
|
rbs
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
11
|
+
io-console (0.6.0)
|
12
|
+
irb (1.6.2)
|
13
|
+
reline (>= 0.3.0)
|
10
14
|
minitest (5.16.3)
|
11
15
|
rake (13.0.6)
|
12
16
|
rbs (2.7.0)
|
17
|
+
reline (0.3.2)
|
18
|
+
io-console (~> 0.5)
|
13
19
|
|
14
20
|
PLATFORMS
|
15
21
|
x86_64-darwin-20
|
@@ -20,4 +26,4 @@ DEPENDENCIES
|
|
20
26
|
rake (~> 13.0)
|
21
27
|
|
22
28
|
BUNDLED WITH
|
23
|
-
2.4.
|
29
|
+
2.4.5
|
data/README.md
CHANGED
@@ -9,9 +9,15 @@ gem install katakata_irb
|
|
9
9
|
```
|
10
10
|
## Usage
|
11
11
|
|
12
|
+
Just require katakata_irb or write it to your `.irbrc` file.
|
13
|
+
```ruby
|
14
|
+
require 'katakata_irb'
|
15
|
+
```
|
16
|
+
|
12
17
|
```
|
13
|
-
|
14
|
-
|
18
|
+
irb(main):001:0> require 'katakata_irb'
|
19
|
+
=> true
|
20
|
+
irb(main):002:0> [1,'a'].sample.a█
|
15
21
|
|[1,'a'].sample.abs |
|
16
22
|
|[1,'a'].sample.abs2 |
|
17
23
|
|[1,'a'].sample.allbits? |
|
@@ -22,30 +28,14 @@ irb(main):001:0> [1,'a'].sample.a█
|
|
22
28
|
```
|
23
29
|
|
24
30
|
```
|
25
|
-
|
26
|
-
|
31
|
+
irb(main):001:0> require 'katakata_irb'
|
32
|
+
=> true
|
33
|
+
irb(main):002:0> a = 10
|
27
34
|
=> 10
|
28
|
-
irb(main):
|
29
|
-
irb(main):
|
30
|
-
irb(main):
|
31
|
-
irb(main):
|
32
|
-
irb(main):
|
35
|
+
irb(main):003:1* if true
|
36
|
+
irb(main):004:2* b = a.times.map do
|
37
|
+
irb(main):005:2* _1.to_s
|
38
|
+
irb(main):006:1* end
|
39
|
+
irb(main):007:1* b[0].a█
|
33
40
|
|b[0].ascii_only?|
|
34
41
|
```
|
35
|
-
|
36
|
-
```ruby
|
37
|
-
require 'katakata_irb/completor'
|
38
|
-
KatakataIrb::Completor.setup
|
39
|
-
10.times do |i|
|
40
|
-
binding.irb
|
41
|
-
end
|
42
|
-
```
|
43
|
-
|
44
|
-
## Options
|
45
|
-
|
46
|
-
### `kirb --debug-output`
|
47
|
-
Show debug output if it meets unimplemented syntax or something
|
48
|
-
|
49
|
-
### `kirb --without-patch`
|
50
|
-
`kirb` will apply some patches to reline and irb/ruby-lex.rb by default. This option will disable it.
|
51
|
-
See `lib/katakata_irb/ruby_lex_patch.rb` and `lib/katakata_irb/reline_patches/*.patch`
|
data/bin/console
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require_relative '../lib/katakata_irb'
|
3
|
-
require_relative '../lib/katakata_irb/reline_patch'
|
4
|
-
KatakataIrb.log_output = STDERR
|
5
|
-
KatakataIrb::RelinePatch.require_patched_reline
|
6
2
|
require 'bundler/setup'
|
7
3
|
require 'katakata_irb'
|
8
|
-
|
9
|
-
|
10
|
-
KatakataIrb.repl
|
4
|
+
KatakataIrb.log_output = STDERR
|
5
|
+
IRB.start(__FILE__)
|
data/katakata_irb.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = "IRB with Typed Completion"
|
13
13
|
spec.homepage = "http://github.com/tompng/katakata_irb"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 3.1.0
|
15
|
+
spec.required_ruby_version = ">= 3.0.0" # recommend >= 3.1.0
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = "http://github.com/tompng/katakata_irb"
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
|
31
31
|
# Uncomment to register a new dependency of your gem
|
32
|
+
spec.add_dependency 'irb', '>= 1.4.0'
|
32
33
|
spec.add_dependency 'rbs'
|
33
34
|
|
34
35
|
# For more information and examples about making a new gem, check out our
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'nesting_parser'
|
2
2
|
require_relative 'type_simulator'
|
3
3
|
require 'rbs'
|
4
4
|
require 'rbs/cli'
|
@@ -6,15 +6,17 @@ require 'irb'
|
|
6
6
|
|
7
7
|
module KatakataIrb::Completor
|
8
8
|
using KatakataIrb::TypeSimulator::LexerElemMatcher
|
9
|
-
|
10
9
|
HIDDEN_METHODS = %w[Namespace TypeName] # defined by rbs, should be hidden
|
10
|
+
singleton_class.attr_accessor :prev_analyze_result
|
11
11
|
|
12
12
|
def self.setup
|
13
13
|
completion_proc = ->(target, preposing = nil, postposing = nil) do
|
14
14
|
code = "#{preposing}#{target}"
|
15
15
|
irb_context = IRB.conf[:MAIN_CONTEXT]
|
16
16
|
binding = irb_context.workspace.binding
|
17
|
-
|
17
|
+
result = analyze code, binding
|
18
|
+
KatakataIrb::Completor.prev_analyze_result = result
|
19
|
+
candidates = case result
|
18
20
|
in [:require | :require_relative => method, name]
|
19
21
|
if method == :require
|
20
22
|
IRB::InputCompletor.retrieve_files_to_require_from_load_path
|
@@ -57,6 +59,44 @@ module KatakataIrb::Completor
|
|
57
59
|
KatakataIrb.log_puts "#{e.inspect} stored to $error"
|
58
60
|
KatakataIrb.log_puts
|
59
61
|
end
|
62
|
+
|
63
|
+
IRB::InputCompletor.singleton_class.prepend Module.new{
|
64
|
+
def retrieve_completion_data(input, _bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
|
65
|
+
return super unless doc_namespace
|
66
|
+
name = input[/[a-zA-Z_0-9]+[!?=]?\z/]
|
67
|
+
method_doc = -> type do
|
68
|
+
type = type.types.find { _1.all_methods.include? name.to_sym }
|
69
|
+
if type in KatakataIrb::Types::SingletonType
|
70
|
+
"#{type.module_or_class.name}.#{name}"
|
71
|
+
elsif type in KatakataIrb::Types::InstanceType
|
72
|
+
"#{type.klass.name}##{name}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
call_or_const_doc = -> type do
|
76
|
+
if name =~ /\A[A-Z]/
|
77
|
+
type = type.types.grep(KatakataIrb::Types::SingletonType).find { _1.module_or_class.const_defined?(name) }
|
78
|
+
type.module_or_class == Object ? name : "#{type.module_or_class.name}::#{name}" if type
|
79
|
+
else
|
80
|
+
method_doc.call(type)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
case KatakataIrb::Completor.prev_analyze_result
|
85
|
+
in [:call_or_const, type, _name, _self_call]
|
86
|
+
call_or_const_doc.call type
|
87
|
+
in [:const, type, _name]
|
88
|
+
# when prev_analyze_result is const, current analyze result might be call
|
89
|
+
call_or_const_doc.call type
|
90
|
+
in [:gvar, _name]
|
91
|
+
name
|
92
|
+
in [:call, type, _name, _self_call]
|
93
|
+
method_doc.call type
|
94
|
+
in [:lvar_or_method, _name, scope]
|
95
|
+
method_doc.call scope.self_type unless scope.local_variables.include?(name)
|
96
|
+
else
|
97
|
+
end
|
98
|
+
end
|
99
|
+
}
|
60
100
|
end
|
61
101
|
|
62
102
|
def self.analyze(code, binding = Kernel.binding)
|
@@ -65,8 +105,8 @@ module KatakataIrb::Completor
|
|
65
105
|
end.join + "nil;\n"
|
66
106
|
code = lvars_code + code
|
67
107
|
tokens = RubyLex.ripper_lex_without_warning code
|
68
|
-
tokens = KatakataIrb::
|
69
|
-
last_opens = KatakataIrb::
|
108
|
+
tokens = KatakataIrb::NestingParser.interpolate_ripper_ignored_tokens code, tokens
|
109
|
+
last_opens = KatakataIrb::NestingParser.parse(tokens)
|
70
110
|
closings = last_opens.map do |t|
|
71
111
|
case t.tok
|
72
112
|
when /\A%.[<>]\z/
|
@@ -89,7 +129,6 @@ module KatakataIrb::Completor
|
|
89
129
|
end
|
90
130
|
end
|
91
131
|
|
92
|
-
return if code =~ /[!?]\z/
|
93
132
|
case tokens.last
|
94
133
|
in { event: :on_ignored_by_ripper, tok: '.' }
|
95
134
|
suffix = 'method'
|
@@ -1,5 +1,4 @@
|
|
1
|
-
module KatakataIrb
|
2
|
-
module KatakataIrb::TRex
|
1
|
+
module KatakataIrb::NestingParser
|
3
2
|
def self.interpolate_ripper_ignored_tokens(code, tokens)
|
4
3
|
line_positions = code.lines.reduce([0]) { _1 << _1.last + _2.bytesize }
|
5
4
|
prev_byte_pos = 0
|
@@ -31,81 +30,102 @@ module KatakataIrb::TRex
|
|
31
30
|
opens = []
|
32
31
|
pending_heredocs = []
|
33
32
|
first_token_on_line = true
|
34
|
-
tokens.
|
33
|
+
tokens.each do |t|
|
35
34
|
skip = false
|
36
35
|
last_tok, state, args = opens.last
|
37
36
|
case state
|
38
37
|
when :in_unquoted_symbol
|
39
|
-
|
40
|
-
|
38
|
+
unless t.event == :on_sp
|
39
|
+
opens.pop
|
40
|
+
skip = true
|
41
|
+
end
|
42
|
+
when :in_lambda_head
|
43
|
+
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
41
44
|
when :in_method_head
|
42
|
-
unless %i[on_sp on_ignored_nl].include?(t.event)
|
45
|
+
unless %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end].include?(t.event)
|
43
46
|
next_args = []
|
44
47
|
body = nil
|
45
|
-
if args.include?
|
48
|
+
if args.include?(:receiver)
|
46
49
|
case t.event
|
47
50
|
when :on_lparen, :on_ivar, :on_gvar, :on_cvar
|
51
|
+
# def (receiver). | def @ivar. | def $gvar. | def @@cvar.
|
48
52
|
next_args << :dot
|
49
53
|
when :on_kw
|
50
|
-
|
51
|
-
|
54
|
+
case t.tok
|
55
|
+
when 'self', 'true', 'false', 'nil'
|
56
|
+
# def self(arg) | def self.
|
57
|
+
next_args.push(:arg, :dot)
|
52
58
|
else
|
59
|
+
# def if(arg)
|
53
60
|
skip = true
|
54
61
|
next_args << :arg
|
55
62
|
end
|
56
|
-
when :on_op
|
63
|
+
when :on_op, :on_backtick
|
64
|
+
# def +(arg)
|
57
65
|
skip = true
|
58
66
|
next_args << :arg
|
59
67
|
when :on_ident, :on_const
|
60
|
-
|
68
|
+
# def a(arg) | def a.
|
69
|
+
next_args.push(:arg, :dot)
|
61
70
|
end
|
62
71
|
end
|
63
|
-
if args.include?
|
72
|
+
if args.include?(:dot)
|
73
|
+
# def receiver.name
|
64
74
|
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
65
75
|
end
|
66
|
-
if args.include?
|
67
|
-
if %i[on_ident on_const on_op on_kw].include?
|
76
|
+
if args.include?(:name)
|
77
|
+
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
78
|
+
# def name(arg) | def receiver.name(arg)
|
68
79
|
next_args << :arg
|
69
80
|
skip = true
|
70
81
|
end
|
71
82
|
end
|
72
|
-
if args.include?
|
83
|
+
if args.include?(:arg)
|
73
84
|
case t.event
|
74
|
-
when :on_op
|
75
|
-
body = :oneliner if t.tok == '='
|
76
85
|
when :on_nl, :on_semicolon
|
86
|
+
# def recever.f;
|
77
87
|
body = :normal
|
78
88
|
when :on_lparen
|
89
|
+
# def recever.f()
|
79
90
|
next_args << :eq
|
80
91
|
else
|
81
|
-
|
92
|
+
if t.event == :on_op && t.tok == '='
|
93
|
+
# def receiver.f =
|
94
|
+
body = :oneliner
|
95
|
+
else
|
96
|
+
# def recever.f arg
|
97
|
+
next_args << :arg_without_paren
|
98
|
+
end
|
82
99
|
end
|
83
100
|
end
|
84
|
-
if args.include?
|
101
|
+
if args.include?(:eq)
|
85
102
|
if t.event == :on_op && t.tok == '='
|
86
103
|
body = :oneliner
|
87
|
-
|
104
|
+
else
|
88
105
|
body = :normal
|
89
106
|
end
|
90
107
|
end
|
91
|
-
if args.include?
|
92
|
-
|
108
|
+
if args.include?(:arg_without_paren)
|
109
|
+
if %i[on_semicolon on_nl].include?(t.event)
|
110
|
+
# def f a;
|
111
|
+
body = :normal
|
112
|
+
else
|
113
|
+
# def f a, b
|
114
|
+
next_args << :arg_without_paren
|
115
|
+
end
|
93
116
|
end
|
94
117
|
if body == :oneliner
|
95
118
|
opens.pop
|
96
119
|
elsif body
|
97
|
-
opens
|
98
|
-
opens << [last_tok, nil]
|
120
|
+
opens[-1] = [last_tok, nil]
|
99
121
|
else
|
100
|
-
opens
|
101
|
-
opens << [last_tok, :in_method_head, next_args]
|
122
|
+
opens[-1] = [last_tok, :in_method_head, next_args]
|
102
123
|
end
|
103
124
|
end
|
104
125
|
when :in_for_while_until_condition
|
105
126
|
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
106
127
|
skip = true if t.event == :on_kw && t.tok == 'do'
|
107
|
-
opens
|
108
|
-
opens << [last_tok, nil]
|
128
|
+
opens[-1] = [last_tok, nil]
|
109
129
|
end
|
110
130
|
end
|
111
131
|
|
@@ -143,6 +163,8 @@ module KatakataIrb::TRex
|
|
143
163
|
opens << [t, nil]
|
144
164
|
end
|
145
165
|
end
|
166
|
+
when :on_tlambda
|
167
|
+
opens << [t, :in_lambda_head]
|
146
168
|
when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
147
169
|
opens << [t, nil]
|
148
170
|
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
@@ -171,10 +193,10 @@ module KatakataIrb::TRex
|
|
171
193
|
first_token_on_line = false
|
172
194
|
end
|
173
195
|
if pending_heredocs.any? && t.tok.include?("\n")
|
174
|
-
pending_heredocs.reverse_each { opens << [
|
196
|
+
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
175
197
|
pending_heredocs = []
|
176
198
|
end
|
177
|
-
yield t,
|
199
|
+
yield t, opens if block_given?
|
178
200
|
end
|
179
201
|
opens.map(&:first) + pending_heredocs.reverse
|
180
202
|
end
|
@@ -184,10 +206,10 @@ module KatakataIrb::TRex
|
|
184
206
|
prev_opens = []
|
185
207
|
min_depth = 0
|
186
208
|
output = []
|
187
|
-
last_opens =
|
209
|
+
last_opens = parse(tokens) do |t, opens|
|
188
210
|
depth = t == opens.last&.first ? opens.size - 1 : opens.size
|
189
211
|
min_depth = depth if depth < min_depth
|
190
|
-
if t.tok.include?
|
212
|
+
if t.tok.include?("\n")
|
191
213
|
t.tok.each_line do |line|
|
192
214
|
line_tokens << [t, line]
|
193
215
|
next if line[-1] != "\n"
|
@@ -31,13 +31,13 @@ class KatakataIrb::TypeSimulator
|
|
31
31
|
fallback = KatakataIrb::Types::NIL
|
32
32
|
case BaseScope.type_by_name name
|
33
33
|
when :cvar
|
34
|
-
KatakataIrb::TypeSimulator.type_of(fallback:) { @self_object.class_variable_get name }
|
34
|
+
KatakataIrb::TypeSimulator.type_of(fallback: fallback) { @self_object.class_variable_get name }
|
35
35
|
when :ivar
|
36
|
-
KatakataIrb::TypeSimulator.type_of(fallback:) { @self_object.instance_variable_get name }
|
36
|
+
KatakataIrb::TypeSimulator.type_of(fallback: fallback) { @self_object.instance_variable_get name }
|
37
37
|
when :lvar
|
38
|
-
KatakataIrb::TypeSimulator.type_of(fallback:) { @binding.local_variable_get(name) }
|
38
|
+
KatakataIrb::TypeSimulator.type_of(fallback: fallback) { @binding.local_variable_get(name) }
|
39
39
|
when :const
|
40
|
-
KatakataIrb::TypeSimulator.type_of(fallback:) { @binding.eval name }
|
40
|
+
KatakataIrb::TypeSimulator.type_of(fallback: fallback) { @binding.eval name }
|
41
41
|
end
|
42
42
|
)
|
43
43
|
end
|
@@ -85,7 +85,7 @@ class KatakataIrb::TypeSimulator
|
|
85
85
|
class Scope
|
86
86
|
attr_reader :parent, :jump_branches
|
87
87
|
|
88
|
-
def self.from_binding(binding) = new
|
88
|
+
def self.from_binding(binding) = new(BaseScope.new(binding, binding.eval('self')))
|
89
89
|
|
90
90
|
def initialize(parent, table = {}, trace_cvar: true, trace_ivar: true, trace_lvar: true, passthrough: false)
|
91
91
|
@tables = [table]
|
@@ -243,8 +243,8 @@ class KatakataIrb::TypeSimulator
|
|
243
243
|
refine Ripper::Lexer::Elem do
|
244
244
|
def deconstruct_keys(_keys)
|
245
245
|
{
|
246
|
-
tok
|
247
|
-
event
|
246
|
+
tok: tok,
|
247
|
+
event: event,
|
248
248
|
label: state.allbits?(Ripper::EXPR_LABEL),
|
249
249
|
beg: state.allbits?(Ripper::EXPR_BEG),
|
250
250
|
dot: state.allbits?(Ripper::EXPR_DOT)
|
@@ -280,7 +280,7 @@ class KatakataIrb::TypeSimulator
|
|
280
280
|
end
|
281
281
|
|
282
282
|
def simulate_evaluate(sexp, scope, case_target: nil)
|
283
|
-
result = simulate_evaluate_inner(sexp, scope, case_target:)
|
283
|
+
result = simulate_evaluate_inner(sexp, scope, case_target: case_target)
|
284
284
|
@dig_targets.resolve result, scope if @dig_targets.target?(sexp)
|
285
285
|
result
|
286
286
|
end
|
@@ -293,7 +293,7 @@ class KatakataIrb::TypeSimulator
|
|
293
293
|
sexp in [:def, _method_name_exp, params, body_stmt]
|
294
294
|
sexp in [:defs, receiver_exp, _dot_exp, _method_name_exp, params, body_stmt]
|
295
295
|
if receiver_exp
|
296
|
-
receiver_exp in
|
296
|
+
receiver_exp in [:paren, receiver_exp]
|
297
297
|
self_type = simulate_evaluate receiver_exp, scope
|
298
298
|
else
|
299
299
|
current_self_types = scope.self_type.types
|
@@ -407,6 +407,9 @@ class KatakataIrb::TypeSimulator
|
|
407
407
|
KatakataIrb::Types::InstanceType.new Hash, K: KatakataIrb::Types::UnionType[*keys], V: KatakataIrb::Types::UnionType[*values]
|
408
408
|
in [:hash, nil]
|
409
409
|
KatakataIrb::Types::InstanceType.new Hash
|
410
|
+
in [:paren, [Symbol,] | false => statement]
|
411
|
+
# workaround for `p ()` and `p (foo)`
|
412
|
+
simulate_evaluate statement, scope if statement
|
410
413
|
in [:paren | :ensure | :else, statements]
|
411
414
|
statements.map { simulate_evaluate _1, scope }.last
|
412
415
|
in [:const_path_ref, receiver, [:@const, name,]]
|
@@ -574,6 +577,7 @@ class KatakataIrb::TypeSimulator
|
|
574
577
|
simulate_evaluate target, scope
|
575
578
|
simulate_evaluate value, scope
|
576
579
|
in [:massign, targets, value]
|
580
|
+
targets in [:mlhs, *targets] # (a,b) = value
|
577
581
|
rhs = simulate_evaluate value, scope
|
578
582
|
evaluate_massign targets, rhs, scope
|
579
583
|
rhs
|
@@ -631,6 +635,8 @@ class KatakataIrb::TypeSimulator
|
|
631
635
|
KatakataIrb::Types::OBJECT
|
632
636
|
in [:redo | :retry]
|
633
637
|
scope.terminate
|
638
|
+
in [:zsuper]
|
639
|
+
KatakataIrb::Types::OBJECT
|
634
640
|
in [:super, args]
|
635
641
|
args, kwargs, _block = retrieve_method_args args
|
636
642
|
args.each do |arg|
|
@@ -717,7 +723,7 @@ class KatakataIrb::TypeSimulator
|
|
717
723
|
end
|
718
724
|
else_branch = lambda do
|
719
725
|
pattern.each { simulate_evaluate _1, scope }
|
720
|
-
simulate_evaluate(else_statement, scope, case_target:)
|
726
|
+
simulate_evaluate(else_statement, scope, case_target: case_target)
|
721
727
|
end
|
722
728
|
if if_statements && else_statement
|
723
729
|
KatakataIrb::Types::UnionType[*scope.run_branches(if_branch, else_branch)]
|
@@ -737,7 +743,7 @@ class KatakataIrb::TypeSimulator
|
|
737
743
|
},
|
738
744
|
-> {
|
739
745
|
pattern_scope.merge_jumps
|
740
|
-
else_statement ? simulate_evaluate(else_statement, scope, case_target:) : KatakataIrb::Types::NIL
|
746
|
+
else_statement ? simulate_evaluate(else_statement, scope, case_target: case_target) : KatakataIrb::Types::NIL
|
741
747
|
}
|
742
748
|
)
|
743
749
|
KatakataIrb::Types::UnionType[*results]
|
@@ -1037,6 +1043,14 @@ class KatakataIrb::TypeSimulator
|
|
1037
1043
|
types = type_breaks.map(&:first)
|
1038
1044
|
breaks = type_breaks.map(&:last).compact
|
1039
1045
|
types << OBJECT_METHODS[method_name.to_sym] if name_match && OBJECT_METHODS.has_key?(method_name.to_sym)
|
1046
|
+
|
1047
|
+
if method_name.to_sym == :new
|
1048
|
+
receiver.types.each do |type|
|
1049
|
+
if (type in KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
|
1050
|
+
types << KatakataIrb::Types::InstanceType.new(type.module_or_class)
|
1051
|
+
end
|
1052
|
+
end
|
1053
|
+
end
|
1040
1054
|
KatakataIrb::Types::UnionType[*types, *breaks]
|
1041
1055
|
end
|
1042
1056
|
|
data/lib/katakata_irb/types.rb
CHANGED
@@ -85,23 +85,26 @@ module KatakataIrb::Types
|
|
85
85
|
|
86
86
|
def self.type_from_object(object, max_level: 4)
|
87
87
|
max_level -= 1
|
88
|
+
sample_size = 1000
|
88
89
|
case object
|
89
90
|
when Array
|
91
|
+
values = object.size > sample_size ? object.sample(sample_size) : object
|
90
92
|
if max_level > 0
|
91
|
-
|
92
|
-
InstanceType.new Array, { Elem: UnionType[*values] }
|
93
|
+
InstanceType.new Array, { Elem: UnionType[*values.map { type_from_object(_1, max_level: max_level) }] }
|
93
94
|
else
|
94
|
-
InstanceType.new Array, { Elem: UnionType[*
|
95
|
+
InstanceType.new Array, { Elem: UnionType[*values.map(&:class).uniq.map { InstanceType.new _1 }] }
|
95
96
|
end
|
96
97
|
when Hash
|
98
|
+
keys = object.size > sample_size ? object.keys.sample(sample_size) : object.keys
|
99
|
+
values = object.size > sample_size ? object.values.sample(sample_size) : object.values
|
97
100
|
if max_level > 0
|
98
|
-
|
99
|
-
|
100
|
-
InstanceType.new Hash, { K: UnionType[*
|
101
|
+
key_types = keys.map { type_from_object(_1, max_level: max_level) }
|
102
|
+
value_types = values.map { type_from_object(_1, max_level: max_level) }
|
103
|
+
InstanceType.new Hash, { K: UnionType[*key_types], V: UnionType[*value_types] }
|
101
104
|
else
|
102
|
-
|
103
|
-
|
104
|
-
InstanceType.new Hash, { K: UnionType[*
|
105
|
+
key_types = keys.map(&:class).uniq.map { InstanceType.new _1 }
|
106
|
+
value_types = values.map(&:class).uniq.map { InstanceType.new _1 }
|
107
|
+
InstanceType.new Hash, { K: UnionType[*key_types], V: UnionType[*value_types] }
|
105
108
|
end
|
106
109
|
when Module
|
107
110
|
SingletonType.new object
|
@@ -117,7 +120,7 @@ module KatakataIrb::Types
|
|
117
120
|
end
|
118
121
|
def transform() = yield(self)
|
119
122
|
def methods() = @module_or_class.methods
|
120
|
-
def all_methods() = methods
|
123
|
+
def all_methods() = methods | Kernel.methods
|
121
124
|
def constants() = @module_or_class.constants
|
122
125
|
def types() = [self]
|
123
126
|
end
|
@@ -294,19 +297,13 @@ module KatakataIrb::Types
|
|
294
297
|
# unimplemented
|
295
298
|
OBJECT
|
296
299
|
when RBS::Types::ClassInstance
|
297
|
-
|
298
|
-
type.module_or_class if (type in SingletonType) && type.module_or_class.is_a?(Class)
|
299
|
-
end
|
300
|
-
if classes.empty?
|
301
|
-
klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
|
302
|
-
classes << klass if klass in Class
|
303
|
-
end
|
300
|
+
klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
|
304
301
|
if return_type.args
|
305
302
|
args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
|
306
303
|
names = rbs_builder.build_singleton(return_type.name).type_params
|
307
304
|
params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
|
308
305
|
end
|
309
|
-
|
306
|
+
InstanceType.new klass, params || {}
|
310
307
|
end
|
311
308
|
end
|
312
309
|
|
data/lib/katakata_irb/version.rb
CHANGED
data/lib/katakata_irb.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
def self.repl
|
4
|
-
require 'katakata_irb/completor'
|
5
|
-
KatakataIrb::Completor.setup
|
6
|
-
IRB.start(__FILE__)
|
7
|
-
end
|
1
|
+
require 'katakata_irb/version'
|
2
|
+
require 'katakata_irb/completor'
|
8
3
|
|
4
|
+
module KatakataIrb
|
9
5
|
def self.log_output=(output)
|
10
6
|
@log_output = output
|
11
7
|
end
|
@@ -14,3 +10,5 @@ module KatakataIrb
|
|
14
10
|
STDOUT.cooked { @log_output&.puts(...) }
|
15
11
|
end
|
16
12
|
end
|
13
|
+
|
14
|
+
KatakataIrb::Completor.setup
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katakata_irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tompng
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: irb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rbs
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -27,8 +41,7 @@ dependencies:
|
|
27
41
|
description: IRB with Typed Completion
|
28
42
|
email:
|
29
43
|
- tomoyapenguin@gmail.com
|
30
|
-
executables:
|
31
|
-
- kirb
|
44
|
+
executables: []
|
32
45
|
extensions: []
|
33
46
|
extra_rdoc_files: []
|
34
47
|
files:
|
@@ -39,19 +52,10 @@ files:
|
|
39
52
|
- Rakefile
|
40
53
|
- bin/console
|
41
54
|
- bin/setup
|
42
|
-
- exe/kirb
|
43
55
|
- katakata_irb.gemspec
|
44
56
|
- lib/katakata_irb.rb
|
45
57
|
- lib/katakata_irb/completor.rb
|
46
|
-
- lib/katakata_irb/
|
47
|
-
- lib/katakata_irb/reline_patches/escapeseq.patch
|
48
|
-
- lib/katakata_irb/reline_patches/fullwidth.patch
|
49
|
-
- lib/katakata_irb/reline_patches/indent.patch
|
50
|
-
- lib/katakata_irb/reline_patches/raw.patch
|
51
|
-
- lib/katakata_irb/reline_patches/scrollbar.patch
|
52
|
-
- lib/katakata_irb/reline_patches/wholelines.patch
|
53
|
-
- lib/katakata_irb/ruby_lex_patch.rb
|
54
|
-
- lib/katakata_irb/trex.rb
|
58
|
+
- lib/katakata_irb/nesting_parser.rb
|
55
59
|
- lib/katakata_irb/type_simulator.rb
|
56
60
|
- lib/katakata_irb/types.rb
|
57
61
|
- lib/katakata_irb/version.rb
|
@@ -70,14 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
74
|
requirements:
|
71
75
|
- - ">="
|
72
76
|
- !ruby/object:Gem::Version
|
73
|
-
version: 3.
|
77
|
+
version: 3.0.0
|
74
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
79
|
requirements:
|
76
80
|
- - ">="
|
77
81
|
- !ruby/object:Gem::Version
|
78
82
|
version: '0'
|
79
83
|
requirements: []
|
80
|
-
rubygems_version: 3.
|
84
|
+
rubygems_version: 3.4.5
|
81
85
|
signing_key:
|
82
86
|
specification_version: 4
|
83
87
|
summary: IRB with Typed Completion
|