katakata_irb 0.1.2 → 0.1.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
- 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
|