typeprof 0.30.1 → 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/lib/typeprof/cli/cli.rb +27 -7
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +85 -24
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +345 -71
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +15 -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 +10 -2
- 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 +37 -12
- data/lib/typeprof/core/graph/box.rb +207 -97
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +4 -21
- data/lib/typeprof/core/service.rb +30 -1
- data/lib/typeprof/core/type.rb +48 -123
- data/lib/typeprof/core.rb +1 -0
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +21 -15
- data/lib/typeprof/lsp/server.rb +132 -39
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -6
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/lib/typeprof/cli/cli.rb
CHANGED
|
@@ -11,6 +11,7 @@ module TypeProf::CLI
|
|
|
11
11
|
|
|
12
12
|
output = nil
|
|
13
13
|
rbs_collection_path = nil
|
|
14
|
+
initialize_config_file = false
|
|
14
15
|
|
|
15
16
|
opt.separator ""
|
|
16
17
|
opt.separator "Options:"
|
|
@@ -39,6 +40,7 @@ module TypeProf::CLI
|
|
|
39
40
|
opt.separator ""
|
|
40
41
|
opt.separator "Advanced options:"
|
|
41
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}
|
|
42
44
|
|
|
43
45
|
opt.separator ""
|
|
44
46
|
opt.separator "LSP options:"
|
|
@@ -47,6 +49,11 @@ module TypeProf::CLI
|
|
|
47
49
|
|
|
48
50
|
opt.parse!(argv)
|
|
49
51
|
|
|
52
|
+
if initialize_config_file
|
|
53
|
+
generate_config_file
|
|
54
|
+
exit 0
|
|
55
|
+
end
|
|
56
|
+
|
|
50
57
|
if !cli_options[:lsp] && !lsp_options.empty?
|
|
51
58
|
raise OptionParser::InvalidOption.new("lsp options with non-lsp mode")
|
|
52
59
|
end
|
|
@@ -101,27 +108,28 @@ module TypeProf::CLI
|
|
|
101
108
|
attr_reader :core_options, :lsp_options, :cli_options
|
|
102
109
|
|
|
103
110
|
def run
|
|
104
|
-
core = TypeProf::Core::Service.new(@core_options)
|
|
105
111
|
|
|
106
112
|
if @cli_options[:lsp]
|
|
107
|
-
run_lsp
|
|
113
|
+
run_lsp
|
|
108
114
|
else
|
|
109
|
-
run_cli
|
|
115
|
+
run_cli
|
|
110
116
|
end
|
|
111
117
|
end
|
|
112
118
|
|
|
113
|
-
def run_lsp
|
|
119
|
+
def run_lsp
|
|
114
120
|
if @lsp_options[:stdio]
|
|
115
|
-
TypeProf::LSP::Server.start_stdio(
|
|
121
|
+
TypeProf::LSP::Server.start_stdio(@core_options)
|
|
116
122
|
else
|
|
117
|
-
TypeProf::LSP::Server.start_socket(
|
|
123
|
+
TypeProf::LSP::Server.start_socket(@core_options)
|
|
118
124
|
end
|
|
119
125
|
rescue Exception
|
|
120
126
|
puts $!.detailed_message(highlight: false).gsub(/^/, "---")
|
|
121
127
|
raise
|
|
122
128
|
end
|
|
123
129
|
|
|
124
|
-
def run_cli
|
|
130
|
+
def run_cli
|
|
131
|
+
core = TypeProf::Core::Service.new(@core_options)
|
|
132
|
+
|
|
125
133
|
puts "typeprof #{ TypeProf::VERSION }" if @cli_options[:display_version]
|
|
126
134
|
|
|
127
135
|
files = find_files
|
|
@@ -174,5 +182,17 @@ module TypeProf::CLI
|
|
|
174
182
|
StackProf.results
|
|
175
183
|
end
|
|
176
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
|
|
177
197
|
end
|
|
178
198
|
end
|
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,19 +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
|
|
|
128
|
-
|
|
154
|
+
block_body = @block_body
|
|
155
|
+
if block_body && block_body.lenv.break_vtx
|
|
129
156
|
ret = Vertex.new(self)
|
|
130
157
|
@changes.add_edge(genv, box.ret, ret)
|
|
131
|
-
@changes.add_edge(genv,
|
|
132
|
-
ret
|
|
158
|
+
@changes.add_edge(genv, block_body.lenv.break_vtx, ret)
|
|
133
159
|
else
|
|
134
|
-
box.ret
|
|
160
|
+
ret = box.ret
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if @safe_navigation
|
|
164
|
+
@changes.add_edge(genv, allow_nil, ret)
|
|
135
165
|
end
|
|
166
|
+
|
|
167
|
+
ret
|
|
136
168
|
end
|
|
137
169
|
|
|
138
170
|
def block_last_stmt_code_range
|
|
@@ -158,10 +190,12 @@ module TypeProf::Core
|
|
|
158
190
|
def modified_vars(tbl, vars)
|
|
159
191
|
subnodes.each do |key, subnode|
|
|
160
192
|
next unless subnode
|
|
161
|
-
if
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
|
165
199
|
else
|
|
166
200
|
subnode.each {|n| n.modified_vars(tbl, vars) }
|
|
167
201
|
end
|
|
@@ -178,6 +212,33 @@ module TypeProf::Core
|
|
|
178
212
|
raw_block = raw_node.block
|
|
179
213
|
super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
|
|
180
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
|
|
181
242
|
end
|
|
182
243
|
|
|
183
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
|
|