typeprof 0.30.0 → 0.31.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.
- checksums.yaml +4 -4
- data/README.md +23 -4
- data/doc/doc.ja.md +1 -1
- data/lib/typeprof/cli/cli.rb +28 -10
- data/lib/typeprof/cli.rb +1 -0
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +90 -21
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +349 -74
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +19 -5
- data/lib/typeprof/core/ast/misc.rb +21 -2
- data/lib/typeprof/core/ast/module.rb +10 -7
- data/lib/typeprof/core/ast/pattern.rb +9 -1
- data/lib/typeprof/core/ast/sig_decl.rb +163 -42
- data/lib/typeprof/core/ast/sig_type.rb +394 -24
- data/lib/typeprof/core/ast/value.rb +11 -3
- data/lib/typeprof/core/ast/variable.rb +32 -2
- data/lib/typeprof/core/ast.rb +15 -4
- data/lib/typeprof/core/builtin.rb +15 -9
- data/lib/typeprof/core/env/method.rb +21 -16
- data/lib/typeprof/core/env/method_entity.rb +11 -2
- data/lib/typeprof/core/env/module_entity.rb +57 -0
- data/lib/typeprof/core/env/narrowing.rb +131 -0
- data/lib/typeprof/core/env/static_read.rb +9 -8
- data/lib/typeprof/core/env.rb +43 -12
- data/lib/typeprof/core/graph/box.rb +218 -101
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +7 -21
- data/lib/typeprof/core/service.rb +61 -40
- data/lib/typeprof/core/type.rb +52 -123
- data/lib/typeprof/core.rb +1 -1
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +27 -36
- data/lib/typeprof/lsp/server.rb +144 -25
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/lsp/util.rb +0 -10
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -5
- data/lib/typeprof/core/graph.rb +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af1ca7b849fb94f4a39e31b3e1b2c45b557936f68099002d69a25d09e2c76b51
|
|
4
|
+
data.tar.gz: cf3d5e1e88614b53a354f874ed0560e6b6bd965468e3be5f024594cf633e4b8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 84eec1b1d33b57ba5022bacab1f194a5942789282c3e19fcb32f2b4d3168f4ff826b5d176982a5ba36b7bbe3bba9f0fef5a0cb927811cba89b759ef337ab72f6
|
|
7
|
+
data.tar.gz: b196e236660ab1814456fd9586e122e135e7773e27c3f49151e6c7a18a015b8ac0562a08c1b740a1d8bcfcd0005c27aefa2dabbaf98085230fcff73933f8028b
|
data/README.md
CHANGED
|
@@ -2,12 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
An experimental type-level Ruby interpreter for testing and understanding Ruby code.
|
|
4
4
|
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install via RubyGems.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
$ gem install typeprof
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Requirements
|
|
14
|
+
|
|
15
|
+
TypeProf supports Ruby 3.3 or later.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
1. Install VSCode [Ruby TypeProf](https://marketplace.visualstudio.com/items?itemName=mame.ruby-typeprof) extension: `code --install-extension mame.ruby-typeprof`
|
|
20
|
+
2. Run `typeprof --init` in your project root to create `typeprof.conf.jsonc` file.
|
|
21
|
+
Other options are available. See [typeprof.conf.jsonc](typeprof.conf.jsonc) for details.
|
|
22
|
+
|
|
23
|
+
3. Reopen your project in VSCode.
|
|
24
|
+
|
|
5
25
|
## Development
|
|
6
26
|
|
|
7
|
-
1.
|
|
8
|
-
2.
|
|
9
|
-
3.
|
|
10
|
-
4. Open the repository in VSCode: `code typeprof`
|
|
27
|
+
1. Git clone this repository: `git clone https://github.com/ruby/typeprof.git`
|
|
28
|
+
2. Install VSCode [Ruby TypeProf](https://marketplace.visualstudio.com/items?itemName=mame.ruby-typeprof) extension: `code --install-extension mame.ruby-typeprof`
|
|
29
|
+
3. Open the repository in VSCode: `code typeprof`
|
|
11
30
|
|
|
12
31
|
### Testing
|
|
13
32
|
|
data/doc/doc.ja.md
CHANGED
data/lib/typeprof/cli/cli.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require "io/console"
|
|
2
|
-
|
|
3
1
|
module TypeProf::CLI
|
|
4
2
|
class CLI
|
|
5
3
|
def initialize(argv)
|
|
@@ -13,6 +11,7 @@ module TypeProf::CLI
|
|
|
13
11
|
|
|
14
12
|
output = nil
|
|
15
13
|
rbs_collection_path = nil
|
|
14
|
+
initialize_config_file = false
|
|
16
15
|
|
|
17
16
|
opt.separator ""
|
|
18
17
|
opt.separator "Options:"
|
|
@@ -41,6 +40,7 @@ module TypeProf::CLI
|
|
|
41
40
|
opt.separator ""
|
|
42
41
|
opt.separator "Advanced options:"
|
|
43
42
|
opt.on("--[no-]stackprof MODE", /\Acpu|wall|object\z/, "Enable stackprof (for debugging purpose)") {|v| cli_options[:stackprof] = v.to_sym }
|
|
43
|
+
opt.on("--init", 'Generate TypeProf configuration file') {|v| initialize_config_file = true}
|
|
44
44
|
|
|
45
45
|
opt.separator ""
|
|
46
46
|
opt.separator "LSP options:"
|
|
@@ -49,7 +49,12 @@ module TypeProf::CLI
|
|
|
49
49
|
|
|
50
50
|
opt.parse!(argv)
|
|
51
51
|
|
|
52
|
-
if
|
|
52
|
+
if initialize_config_file
|
|
53
|
+
generate_config_file
|
|
54
|
+
exit 0
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if !cli_options[:lsp] && !lsp_options.empty?
|
|
53
58
|
raise OptionParser::InvalidOption.new("lsp options with non-lsp mode")
|
|
54
59
|
end
|
|
55
60
|
|
|
@@ -103,27 +108,28 @@ module TypeProf::CLI
|
|
|
103
108
|
attr_reader :core_options, :lsp_options, :cli_options
|
|
104
109
|
|
|
105
110
|
def run
|
|
106
|
-
core = TypeProf::Core::Service.new(@core_options)
|
|
107
111
|
|
|
108
112
|
if @cli_options[:lsp]
|
|
109
|
-
run_lsp
|
|
113
|
+
run_lsp
|
|
110
114
|
else
|
|
111
|
-
run_cli
|
|
115
|
+
run_cli
|
|
112
116
|
end
|
|
113
117
|
end
|
|
114
118
|
|
|
115
|
-
def run_lsp
|
|
119
|
+
def run_lsp
|
|
116
120
|
if @lsp_options[:stdio]
|
|
117
|
-
TypeProf::LSP::Server.start_stdio(
|
|
121
|
+
TypeProf::LSP::Server.start_stdio(@core_options)
|
|
118
122
|
else
|
|
119
|
-
TypeProf::LSP::Server.start_socket(
|
|
123
|
+
TypeProf::LSP::Server.start_socket(@core_options)
|
|
120
124
|
end
|
|
121
125
|
rescue Exception
|
|
122
126
|
puts $!.detailed_message(highlight: false).gsub(/^/, "---")
|
|
123
127
|
raise
|
|
124
128
|
end
|
|
125
129
|
|
|
126
|
-
def run_cli
|
|
130
|
+
def run_cli
|
|
131
|
+
core = TypeProf::Core::Service.new(@core_options)
|
|
132
|
+
|
|
127
133
|
puts "typeprof #{ TypeProf::VERSION }" if @cli_options[:display_version]
|
|
128
134
|
|
|
129
135
|
files = find_files
|
|
@@ -176,5 +182,17 @@ module TypeProf::CLI
|
|
|
176
182
|
StackProf.results
|
|
177
183
|
end
|
|
178
184
|
end
|
|
185
|
+
|
|
186
|
+
def generate_config_file
|
|
187
|
+
exist_dirs = ["app", "lib"].select { |dir| File.exist?(File.join(Dir.pwd, dir)) }
|
|
188
|
+
File.write('typeprof.conf.jsonc', <<~JSONC, mode: "wx")
|
|
189
|
+
{
|
|
190
|
+
"typeprof_version": "experimental",
|
|
191
|
+
"rbs_dir": "sig/",
|
|
192
|
+
"analysis_unit_dirs": #{exist_dirs.inspect}
|
|
193
|
+
// "diagnostic_severity": "warning"
|
|
194
|
+
}
|
|
195
|
+
JSONC
|
|
196
|
+
end
|
|
179
197
|
end
|
|
180
198
|
end
|
data/lib/typeprof/cli.rb
CHANGED
data/lib/typeprof/code_range.rb
CHANGED
|
@@ -56,16 +56,13 @@ module TypeProf
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def self.from_node(node, encoding = Encoding::UTF_16LE)
|
|
59
|
-
node = node.location if node.
|
|
59
|
+
node = node.location if node.respond_to?(:location)
|
|
60
60
|
if node.is_a?(Prism::Location)
|
|
61
61
|
pos1 = CodePosition.new(node.start_line, node.start_code_units_column(encoding))
|
|
62
62
|
pos2 = CodePosition.new(node.end_line, node.end_code_units_column(encoding))
|
|
63
|
-
elsif node.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
pos1 = CodePosition.new(row, col) # TODO: use SPLAT
|
|
67
|
-
row, col = loc.end_loc
|
|
68
|
-
pos2 = CodePosition.new(row, col)
|
|
63
|
+
elsif node.is_a?(RBS::Location)
|
|
64
|
+
pos1 = CodePosition.new(*node.start_loc)
|
|
65
|
+
pos2 = CodePosition.new(*node.end_loc)
|
|
69
66
|
else
|
|
70
67
|
p node.class.ancestors
|
|
71
68
|
raise "unknown type: #{ node.class }"
|
|
@@ -108,5 +105,10 @@ module TypeProf
|
|
|
108
105
|
def ==(other)
|
|
109
106
|
@first == other.first && @last == other.last
|
|
110
107
|
end
|
|
108
|
+
|
|
109
|
+
def <=>(other)
|
|
110
|
+
cmp = @first <=> other.first
|
|
111
|
+
cmp == 0 ? @last <=> other.last : cmp
|
|
112
|
+
end
|
|
111
113
|
end
|
|
112
114
|
end
|
|
@@ -9,6 +9,7 @@ module TypeProf::Core
|
|
|
9
9
|
@ret = nil
|
|
10
10
|
|
|
11
11
|
@changes = ChangeSet.new(self, nil)
|
|
12
|
+
@diagnostics = Set[]
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
attr_reader :lenv
|
|
@@ -16,6 +17,7 @@ module TypeProf::Core
|
|
|
16
17
|
attr_reader :static_ret
|
|
17
18
|
attr_reader :ret
|
|
18
19
|
attr_reader :changes
|
|
20
|
+
attr_reader :diagnostics
|
|
19
21
|
|
|
20
22
|
def subnodes = {}
|
|
21
23
|
def attrs = {}
|
|
@@ -63,12 +65,12 @@ module TypeProf::Core
|
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
def define_copy(genv)
|
|
66
|
-
@lenv = @prev_node.lenv
|
|
68
|
+
@lenv = (@prev_node || raise).lenv
|
|
67
69
|
each_subnode do |subnode|
|
|
68
70
|
subnode.define_copy(genv)
|
|
69
71
|
end
|
|
70
72
|
@prev_node.instance_variable_set(:@reused, true)
|
|
71
|
-
@static_ret = @prev_node.static_ret
|
|
73
|
+
@static_ret = (@prev_node || raise).static_ret
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def define0(genv)
|
|
@@ -90,6 +92,7 @@ module TypeProf::Core
|
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
|
|
95
|
+
#: (TypeProf::Core::GlobalEnv) -> TypeProf::Core::BasicVertex
|
|
93
96
|
def install(genv)
|
|
94
97
|
@ret = install0(genv)
|
|
95
98
|
@changes.reinstall(genv)
|
|
@@ -97,14 +100,19 @@ module TypeProf::Core
|
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
def install_copy(genv)
|
|
100
|
-
@changes.copy_from(@prev_node.changes)
|
|
103
|
+
@changes.copy_from((@prev_node || raise).changes)
|
|
101
104
|
@changes.reuse(self)
|
|
105
|
+
(@prev_node || raise).diagnostics.each do |diag|
|
|
106
|
+
diag.reuse(self)
|
|
107
|
+
@diagnostics << diag
|
|
108
|
+
end
|
|
102
109
|
each_subnode do |subnode|
|
|
103
110
|
subnode.install_copy(genv)
|
|
104
111
|
end
|
|
105
|
-
@ret = @prev_node.ret
|
|
112
|
+
@ret = (@prev_node || raise).ret
|
|
106
113
|
end
|
|
107
114
|
|
|
115
|
+
#: (TypeProf::Core::GlobalEnv) -> untyped
|
|
108
116
|
def install0(_)
|
|
109
117
|
raise "should override"
|
|
110
118
|
end
|
|
@@ -116,6 +124,18 @@ module TypeProf::Core
|
|
|
116
124
|
end
|
|
117
125
|
end
|
|
118
126
|
|
|
127
|
+
def narrowings
|
|
128
|
+
Narrowing::EmptyNarrowings
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def add_diagnostic(diag)
|
|
132
|
+
@diagnostics << diag
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def remove_diagnostic(diag)
|
|
136
|
+
@diagnostics.delete(diag)
|
|
137
|
+
end
|
|
138
|
+
|
|
119
139
|
def diff(prev_node)
|
|
120
140
|
if prev_node.is_a?(self.class) && attrs.all? {|key, attr| attr == prev_node.send(key) }
|
|
121
141
|
raise unless prev_node # annotation
|
|
@@ -159,13 +179,10 @@ module TypeProf::Core
|
|
|
159
179
|
end
|
|
160
180
|
end
|
|
161
181
|
|
|
162
|
-
def
|
|
163
|
-
@
|
|
164
|
-
@changes.boxes.each_value do |box|
|
|
165
|
-
box.diagnostics(genv, &blk)
|
|
166
|
-
end
|
|
182
|
+
def each_diagnostic(genv, &blk)
|
|
183
|
+
@diagnostics.each(&blk)
|
|
167
184
|
each_subnode do |subnode|
|
|
168
|
-
subnode.
|
|
185
|
+
subnode.each_diagnostic(genv, &blk)
|
|
169
186
|
end
|
|
170
187
|
end
|
|
171
188
|
|
|
@@ -17,22 +17,28 @@ module TypeProf::Core
|
|
|
17
17
|
@block_tbl = nil
|
|
18
18
|
@block_f_args = nil
|
|
19
19
|
@block_body = nil
|
|
20
|
+
@safe_navigation = raw_node.respond_to?(:safe_navigation?) && raw_node.safe_navigation?
|
|
21
|
+
@anonymous_block_forwarding = false
|
|
20
22
|
|
|
21
23
|
if raw_args
|
|
22
24
|
args = []
|
|
23
25
|
@splat_flags = []
|
|
24
26
|
raw_args.arguments.each do |raw_arg|
|
|
25
|
-
|
|
27
|
+
case raw_arg
|
|
28
|
+
when Prism::SplatNode
|
|
26
29
|
args << raw_arg.expression
|
|
27
30
|
@splat_flags << true
|
|
31
|
+
when Prism::ForwardingArgumentsNode
|
|
32
|
+
# TODO: Support forwarding arguments
|
|
28
33
|
else
|
|
29
34
|
args << raw_arg
|
|
30
35
|
@splat_flags << false
|
|
31
36
|
end
|
|
32
37
|
end
|
|
33
|
-
@positional_args = args.map {|arg| AST.create_node(arg, lenv) }
|
|
38
|
+
@positional_args = args.map {|arg| arg ? AST.create_node(arg, lenv) : DummyNilNode.new(code_range, lenv) }
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
kw = @positional_args.last
|
|
41
|
+
if kw.is_a?(TypeProf::Core::AST::HashNode) && kw.keywords
|
|
36
42
|
@keyword_args = @positional_args.pop
|
|
37
43
|
end
|
|
38
44
|
end
|
|
@@ -41,7 +47,11 @@ module TypeProf::Core
|
|
|
41
47
|
|
|
42
48
|
if raw_block
|
|
43
49
|
if raw_block.type == :block_argument_node
|
|
44
|
-
|
|
50
|
+
if raw_block.expression
|
|
51
|
+
@block_pass = AST.create_node(raw_block.expression, lenv)
|
|
52
|
+
else
|
|
53
|
+
@anonymous_block_forwarding = true
|
|
54
|
+
end
|
|
45
55
|
else
|
|
46
56
|
@block_pass = nil
|
|
47
57
|
@block_tbl = raw_block.locals
|
|
@@ -51,6 +61,8 @@ module TypeProf::Core
|
|
|
51
61
|
raw_block.parameters.parameters.requireds.map {|n| n.is_a?(Prism::MultiTargetNode) ? nil : n.name }
|
|
52
62
|
when Prism::NumberedParametersNode
|
|
53
63
|
1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" }
|
|
64
|
+
when Prism::ItParametersNode
|
|
65
|
+
[:it]
|
|
54
66
|
when nil
|
|
55
67
|
[]
|
|
56
68
|
else
|
|
@@ -67,51 +79,63 @@ module TypeProf::Core
|
|
|
67
79
|
|
|
68
80
|
attr_reader :recv, :mid, :mid_code_range, :yield
|
|
69
81
|
attr_reader :positional_args, :splat_flags, :keyword_args
|
|
70
|
-
attr_reader :block_tbl, :block_f_args, :block_body, :block_pass
|
|
82
|
+
attr_reader :block_tbl, :block_f_args, :block_body, :block_pass, :anonymous_block_forwarding
|
|
83
|
+
attr_reader :safe_navigation
|
|
71
84
|
|
|
72
85
|
def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: }
|
|
73
|
-
def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: }
|
|
86
|
+
def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield:, safe_navigation:, anonymous_block_forwarding: }
|
|
74
87
|
|
|
75
88
|
def install0(genv)
|
|
76
89
|
recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self")
|
|
77
90
|
|
|
91
|
+
if @safe_navigation
|
|
92
|
+
allow_nil = NilFilter.new(genv, self, recv, true).next_vtx
|
|
93
|
+
recv = NilFilter.new(genv, self, recv, false).next_vtx
|
|
94
|
+
end
|
|
95
|
+
|
|
78
96
|
positional_args = @positional_args.map do |arg|
|
|
79
|
-
arg.
|
|
97
|
+
if arg.is_a?(DummyNilNode)
|
|
98
|
+
@lenv.get_var(:"*anonymous_rest")
|
|
99
|
+
else
|
|
100
|
+
arg.install(genv)
|
|
101
|
+
end
|
|
80
102
|
end
|
|
81
103
|
|
|
82
104
|
keyword_args = @keyword_args ? @keyword_args.install(genv) : nil
|
|
83
105
|
|
|
84
106
|
if @block_body
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
block_body = @block_body # kinda type annotationty
|
|
108
|
+
block_tbl = @block_tbl || raise
|
|
109
|
+
@lenv.locals.each {|var, vtx| block_body.lenv.locals[var] = vtx }
|
|
110
|
+
block_tbl.each {|var| block_body.lenv.locals[var] = Source.new(genv.nil_type) }
|
|
87
111
|
@block_body.lenv.locals[:"*self"] = @block_body.lenv.cref.get_self(genv)
|
|
88
112
|
|
|
89
113
|
blk_f_args = []
|
|
90
114
|
if @block_f_args
|
|
91
115
|
@block_f_args.each do |arg|
|
|
92
|
-
blk_f_args <<
|
|
116
|
+
blk_f_args << block_body.lenv.new_var(arg, self)
|
|
93
117
|
end
|
|
94
118
|
end
|
|
95
119
|
|
|
96
120
|
@lenv.locals.each do |var, vtx|
|
|
97
|
-
|
|
121
|
+
block_body.lenv.set_var(var, vtx)
|
|
98
122
|
end
|
|
99
123
|
vars = []
|
|
100
|
-
@block_body.modified_vars(@lenv.locals.keys -
|
|
124
|
+
@block_body.modified_vars(@lenv.locals.keys - block_tbl, vars)
|
|
101
125
|
vars.uniq!
|
|
102
126
|
vars.each do |var|
|
|
103
127
|
vtx = @lenv.get_var(var)
|
|
104
128
|
nvtx = vtx.new_vertex(genv, self)
|
|
105
129
|
@lenv.set_var(var, nvtx)
|
|
106
|
-
|
|
130
|
+
block_body.lenv.set_var(var, nvtx)
|
|
107
131
|
end
|
|
108
132
|
|
|
109
|
-
|
|
133
|
+
@block_body.lenv.locals[:"*expected_block_ret"] = Vertex.new(self)
|
|
110
134
|
@block_body.install(genv)
|
|
111
|
-
@block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret
|
|
135
|
+
@block_body.lenv.add_next_box(@changes.add_escape_box(genv, @block_body.ret))
|
|
112
136
|
|
|
113
137
|
vars.each do |var|
|
|
114
|
-
@changes.add_edge(genv,
|
|
138
|
+
@changes.add_edge(genv, block_body.lenv.get_var(var), @lenv.get_var(var))
|
|
115
139
|
end
|
|
116
140
|
|
|
117
141
|
blk_f_ary_arg = Vertex.new(self)
|
|
@@ -120,11 +144,27 @@ module TypeProf::Core
|
|
|
120
144
|
blk_ty = Source.new(Type::Proc.new(genv, block))
|
|
121
145
|
elsif @block_pass
|
|
122
146
|
blk_ty = @block_pass.install(genv)
|
|
147
|
+
elsif @anonymous_block_forwarding
|
|
148
|
+
blk_ty = @lenv.get_var(:"*anonymous_block")
|
|
123
149
|
end
|
|
124
150
|
|
|
125
151
|
a_args = ActualArguments.new(positional_args, @splat_flags, keyword_args, blk_ty)
|
|
126
152
|
box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv)
|
|
127
|
-
|
|
153
|
+
|
|
154
|
+
block_body = @block_body
|
|
155
|
+
if block_body && block_body.lenv.break_vtx
|
|
156
|
+
ret = Vertex.new(self)
|
|
157
|
+
@changes.add_edge(genv, box.ret, ret)
|
|
158
|
+
@changes.add_edge(genv, block_body.lenv.break_vtx, ret)
|
|
159
|
+
else
|
|
160
|
+
ret = box.ret
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if @safe_navigation
|
|
164
|
+
@changes.add_edge(genv, allow_nil, ret)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
ret
|
|
128
168
|
end
|
|
129
169
|
|
|
130
170
|
def block_last_stmt_code_range
|
|
@@ -150,10 +190,12 @@ module TypeProf::Core
|
|
|
150
190
|
def modified_vars(tbl, vars)
|
|
151
191
|
subnodes.each do |key, subnode|
|
|
152
192
|
next unless subnode
|
|
153
|
-
if
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
193
|
+
if subnode.is_a?(AST::Node)
|
|
194
|
+
if key == :block_body
|
|
195
|
+
subnode.modified_vars(tbl - self.block_tbl, vars)
|
|
196
|
+
else
|
|
197
|
+
subnode.modified_vars(tbl, vars)
|
|
198
|
+
end
|
|
157
199
|
else
|
|
158
200
|
subnode.each {|n| n.modified_vars(tbl, vars) }
|
|
159
201
|
end
|
|
@@ -170,6 +212,33 @@ module TypeProf::Core
|
|
|
170
212
|
raw_block = raw_node.block
|
|
171
213
|
super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
|
|
172
214
|
end
|
|
215
|
+
|
|
216
|
+
def narrowings
|
|
217
|
+
@narrowings ||= begin
|
|
218
|
+
args = @positional_args
|
|
219
|
+
case @mid
|
|
220
|
+
when :is_a?
|
|
221
|
+
if @recv.is_a?(LocalVariableReadNode) && args && args.size == 1
|
|
222
|
+
[
|
|
223
|
+
Narrowing.new({ @recv.var => Narrowing::IsAConstraint.new(args[0], false) }),
|
|
224
|
+
Narrowing.new({ @recv.var => Narrowing::IsAConstraint.new(args[0], true) })
|
|
225
|
+
]
|
|
226
|
+
elsif @recv.is_a?(InstanceVariableReadNode) && args && args.size == 1
|
|
227
|
+
[
|
|
228
|
+
Narrowing.new({ @recv.var => Narrowing::IsAConstraint.new(args[0], false) }),
|
|
229
|
+
Narrowing.new({ @recv.var => Narrowing::IsAConstraint.new(args[0], true) })
|
|
230
|
+
]
|
|
231
|
+
else
|
|
232
|
+
super
|
|
233
|
+
end
|
|
234
|
+
when :!
|
|
235
|
+
then_narrowing, else_narrowing = @recv.narrowings
|
|
236
|
+
[else_narrowing, then_narrowing]
|
|
237
|
+
else
|
|
238
|
+
super
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
173
242
|
end
|
|
174
243
|
|
|
175
244
|
class SuperNode < CallBaseNode
|
|
@@ -17,29 +17,24 @@ module TypeProf::Core
|
|
|
17
17
|
@cbase = nil
|
|
18
18
|
@toplevel = true
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@cname = raw_node.name
|
|
23
|
-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
|
|
24
|
-
else
|
|
25
|
-
@cname = raw_node.child.name
|
|
26
|
-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.child.location)
|
|
27
|
-
end
|
|
20
|
+
@cname = raw_node.name
|
|
21
|
+
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
|
|
28
22
|
else
|
|
29
23
|
raise raw_node.type.to_s
|
|
30
24
|
end
|
|
25
|
+
@strict_const_scope = lenv.strict_const_scope
|
|
31
26
|
end
|
|
32
27
|
|
|
33
|
-
attr_reader :cname, :cbase, :toplevel, :cname_code_range
|
|
28
|
+
attr_reader :cname, :cbase, :toplevel, :cname_code_range, :strict_const_scope
|
|
34
29
|
|
|
35
|
-
def attrs = { cname:, toplevel: }
|
|
30
|
+
def attrs = { cname:, toplevel:, strict_const_scope: }
|
|
36
31
|
def subnodes = { cbase: }
|
|
37
32
|
|
|
38
33
|
def define0(genv)
|
|
39
34
|
if @cbase
|
|
40
|
-
ScopedConstRead.new(@cname, @cbase.define(genv))
|
|
35
|
+
ScopedConstRead.new(@cname, @cbase.define(genv), @strict_const_scope)
|
|
41
36
|
else
|
|
42
|
-
BaseConstRead.new(genv, @cname, @toplevel ? CRef::Toplevel : @lenv.cref)
|
|
37
|
+
BaseConstRead.new(genv, @cname, @toplevel ? CRef::Toplevel : @lenv.cref, @strict_const_scope)
|
|
43
38
|
end
|
|
44
39
|
end
|
|
45
40
|
|