typeprof 0.21.3 → 0.21.5
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/.github/dependabot.yml +6 -0
- data/.github/workflows/main.yml +18 -5
- data/Gemfile +7 -3
- data/Gemfile.lock +4 -4
- data/lib/typeprof/analyzer.rb +4 -2
- data/lib/typeprof/import.rb +38 -10
- data/lib/typeprof/iseq.rb +34 -6
- data/lib/typeprof/type.rb +9 -4
- data/lib/typeprof/version.rb +1 -1
- data/lib/typeprof.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f5c0fba3561953bdf7db3fe5c326cd4a8375376189928270d919f23dffd78ce
|
4
|
+
data.tar.gz: b3d7aabe2f15298c41de661308e3d757ed0643df079092fe184f6046cc9336c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b861fb63e8cfb3d39fdf5a5f753ea88041e730d5c8518098c05fa07f360eae8f3f808697e5e0462ffc76def30e7163c184a95e3bd14a941063c3dc523a9fad53
|
7
|
+
data.tar.gz: 6b061ce0869738ea048e85c74a018adc8894f1c05d71c61b0e91d93b0714c177ef2bc48499640a97fc5f43fd29ace9227ef13924df006a81239cf2ac50480087
|
data/.github/workflows/main.yml
CHANGED
@@ -1,25 +1,38 @@
|
|
1
1
|
name: Ruby
|
2
2
|
|
3
|
-
on:
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
pull_request:
|
6
|
+
workflow_dispatch:
|
7
|
+
schedule:
|
8
|
+
- cron: '11 24 * * 5'
|
4
9
|
|
5
10
|
jobs:
|
11
|
+
ruby-versions:
|
12
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
13
|
+
with:
|
14
|
+
engine: cruby-truffleruby
|
15
|
+
min_version: 2.7
|
16
|
+
|
6
17
|
build:
|
18
|
+
needs: ruby-versions
|
19
|
+
name: build (${{ matrix.ruby }})
|
7
20
|
strategy:
|
8
21
|
fail-fast: false
|
9
22
|
matrix:
|
10
|
-
ruby
|
23
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
11
24
|
runs-on: ubuntu-latest
|
12
25
|
steps:
|
13
26
|
- uses: actions/checkout@v3
|
14
|
-
with:
|
15
|
-
submodules: true
|
16
27
|
- name: Set up Ruby
|
17
28
|
uses: ruby/setup-ruby@v1
|
18
29
|
with:
|
19
|
-
ruby-version: ${{ matrix.ruby
|
30
|
+
ruby-version: ${{ matrix.ruby }}
|
20
31
|
- name: Bundle install
|
21
32
|
run: |
|
22
33
|
bundle install
|
34
|
+
- run: bundle exec typeprof --version
|
23
35
|
- name: Run the test suite
|
24
36
|
run: |
|
25
37
|
bundle exec rake TESTOPT=-v
|
38
|
+
if: ${{ !startsWith(matrix.ruby, 'truffle') }}
|
data/Gemfile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
if ENV["RBS_VERSION"]
|
4
|
+
gem "rbs", github: "ruby/rbs", ref: ENV["RBS_VERSION"]
|
5
|
+
else
|
6
|
+
# Specify your gem's dependencies in typeprof.gemspec
|
7
|
+
gemspec
|
8
|
+
end
|
5
9
|
|
6
10
|
group :development do
|
7
11
|
gem "rake"
|
8
|
-
gem "stackprof"
|
12
|
+
gem "stackprof", platforms: :mri
|
9
13
|
gem "test-unit"
|
10
14
|
gem "simplecov"
|
11
15
|
gem "simplecov-html"
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.21.
|
4
|
+
typeprof (0.21.5)
|
5
5
|
rbs (>= 1.8.1)
|
6
6
|
|
7
7
|
GEM
|
@@ -10,8 +10,8 @@ GEM
|
|
10
10
|
coverage-helpers (1.0.0)
|
11
11
|
docile (1.4.0)
|
12
12
|
power_assert (2.0.1)
|
13
|
-
rake (13.0.
|
14
|
-
rbs (
|
13
|
+
rake (13.0.1)
|
14
|
+
rbs (3.0.0)
|
15
15
|
simplecov (0.21.2)
|
16
16
|
docile (~> 1.1)
|
17
17
|
simplecov-html (~> 0.11)
|
@@ -36,4 +36,4 @@ DEPENDENCIES
|
|
36
36
|
typeprof!
|
37
37
|
|
38
38
|
BUNDLED WITH
|
39
|
-
2.
|
39
|
+
2.3.11
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -1997,7 +1997,8 @@ module TypeProf
|
|
1997
1997
|
env = env.push(Type.any) # or String | NilClass only?
|
1998
1998
|
when 1 # VM_SVAR_BACKREF ($~)
|
1999
1999
|
merge_env(ep.next, env.push(Type::Instance.new(Type::Builtin[:matchdata])))
|
2000
|
-
|
2000
|
+
# tentatively disabled; it is too conservative
|
2001
|
+
#merge_env(ep.next, env.push(Type.nil))
|
2001
2002
|
return
|
2002
2003
|
else # flip-flop
|
2003
2004
|
env = env.push(Type.bool)
|
@@ -2005,7 +2006,8 @@ module TypeProf
|
|
2005
2006
|
else
|
2006
2007
|
# NTH_REF ($1, $2, ...) / BACK_REF ($&, $+, ...)
|
2007
2008
|
merge_env(ep.next, env.push(Type::Instance.new(Type::Builtin[:str])))
|
2008
|
-
|
2009
|
+
# tentatively disabled; it is too conservative
|
2010
|
+
#merge_env(ep.next, env.push(Type.nil))
|
2009
2011
|
return
|
2010
2012
|
end
|
2011
2013
|
when :setspecial
|
data/lib/typeprof/import.rb
CHANGED
@@ -7,6 +7,7 @@ module TypeProf
|
|
7
7
|
collection_path = Config.current.collection_path
|
8
8
|
if collection_path&.exist?
|
9
9
|
collection_lock = RBS::Collection::Config.lockfile_of(collection_path)
|
10
|
+
raise "Please execute 'rbs collection install'" if collection_lock.nil?
|
10
11
|
@repo.add(collection_lock.repo_path)
|
11
12
|
end
|
12
13
|
@env, @loaded_gems, @builtin_env_json = RBSReader.get_builtin_env
|
@@ -77,19 +78,37 @@ module TypeProf
|
|
77
78
|
def load_rbs_string(name, content)
|
78
79
|
buffer = RBS::Buffer.new(name: name, content: content)
|
79
80
|
new_decls = []
|
80
|
-
RBS::Parser.parse_signature(buffer)
|
81
|
-
|
82
|
-
|
81
|
+
ret = RBS::Parser.parse_signature(buffer)
|
82
|
+
if ret[0].is_a?(RBS::Buffer)
|
83
|
+
# rbs 3.0
|
84
|
+
buffer, directives, decls = ret
|
85
|
+
@env.add_signature(buffer: buffer, directives: directives, decls: decls)
|
86
|
+
new_decls.concat(decls)
|
87
|
+
else
|
88
|
+
ret.each do |decl|
|
89
|
+
@env << decl
|
90
|
+
new_decls << decl
|
91
|
+
end
|
83
92
|
end
|
84
93
|
RBSReader.load_rbs(@env, new_decls)
|
85
94
|
end
|
86
95
|
|
87
96
|
def self.load_rbs(env, new_decls)
|
88
97
|
all_env = env.resolve_type_names
|
89
|
-
resolver = RBS::TypeNameResolver.from_env(all_env)
|
90
98
|
cur_env = RBS::Environment.new
|
91
|
-
|
92
|
-
|
99
|
+
if defined?(RBS::TypeNameResolver)
|
100
|
+
resolver = RBS::TypeNameResolver.from_env(all_env)
|
101
|
+
new_decls.each do |decl|
|
102
|
+
cur_env << env.resolve_declaration(resolver, decl, outer: [], prefix: RBS::Namespace.root)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
resolver = RBS::Resolver::TypeNameResolver.new(all_env)
|
106
|
+
table = RBS::Environment::UseMap::Table.new()
|
107
|
+
table.compute_children
|
108
|
+
map = RBS::Environment::UseMap.new(table: table)
|
109
|
+
new_decls.each do |decl|
|
110
|
+
cur_env << s = env.resolve_declaration(resolver, map, decl, outer: [], prefix: RBS::Namespace.root)
|
111
|
+
end
|
93
112
|
end
|
94
113
|
|
95
114
|
RBS2JSON.new(all_env, cur_env).dump_json
|
@@ -134,6 +153,9 @@ module TypeProf
|
|
134
153
|
gvars
|
135
154
|
end
|
136
155
|
|
156
|
+
AliasDecl = defined?(RBS::AST::Declarations::Alias) ? RBS::AST::Declarations::Alias : RBS::AST::Declarations::AliasDecl
|
157
|
+
TypeAlias = defined?(RBS::AST::Declarations::TypeAlias) ? RBS::AST::Declarations::TypeAlias : nil
|
158
|
+
|
137
159
|
def conv_classes
|
138
160
|
json = {}
|
139
161
|
|
@@ -170,7 +192,12 @@ module TypeProf
|
|
170
192
|
when RBS::AST::Members::MethodDefinition
|
171
193
|
name = member.name
|
172
194
|
|
173
|
-
|
195
|
+
if member.respond_to?(:overloads)
|
196
|
+
types = member.overloads.map {|overload| overload.method_type }
|
197
|
+
else
|
198
|
+
types = member.types
|
199
|
+
end
|
200
|
+
method_types = types.map do |method_type|
|
174
201
|
case method_type
|
175
202
|
when RBS::MethodType then method_type
|
176
203
|
when :super then raise NotImplementedError
|
@@ -180,7 +207,7 @@ module TypeProf
|
|
180
207
|
method_def = conv_method_def(method_types, visibility)
|
181
208
|
rbs_source = [
|
182
209
|
(member.kind == :singleton ? "self." : "") + member.name.to_s,
|
183
|
-
|
210
|
+
types.map {|type| type.location.source },
|
184
211
|
[member.location.name, CodeRange.from_rbs(member.location)],
|
185
212
|
]
|
186
213
|
if member.instance?
|
@@ -260,9 +287,10 @@ module TypeProf
|
|
260
287
|
|
261
288
|
# The following declarations are ignoreable because they are handled in other level
|
262
289
|
when RBS::AST::Declarations::Constant
|
263
|
-
when
|
290
|
+
when AliasDecl # type alias
|
264
291
|
when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
|
265
292
|
when RBS::AST::Declarations::Interface
|
293
|
+
when TypeAlias
|
266
294
|
|
267
295
|
else
|
268
296
|
warn "Importing #{ member.class.name } is not supported yet"
|
@@ -487,7 +515,7 @@ module TypeProf
|
|
487
515
|
else
|
488
516
|
begin
|
489
517
|
@alias_resolution_stack[ty.name] = true
|
490
|
-
alias_decl = @all_env.alias_decls[ty.name]
|
518
|
+
alias_decl = (@all_env.respond_to?(:alias_decls) ? @all_env.alias_decls : @all_env.type_alias_decls)[ty.name]
|
491
519
|
alias_decl ? conv_type(alias_decl.decl.type) : [:any]
|
492
520
|
ensure
|
493
521
|
@alias_resolution_stack.delete(ty.name)
|
data/lib/typeprof/iseq.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
module TypeProf
|
2
2
|
class ISeq
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
if defined?(RubyVM::InstructionSequence)
|
4
|
+
# https://github.com/ruby/ruby/pull/4468
|
5
|
+
CASE_WHEN_CHECKMATCH = RubyVM::InstructionSequence.compile("case 1; when Integer; end").to_a.last.any? {|insn,| insn == :checkmatch }
|
6
|
+
# https://github.com/ruby/ruby/blob/v3_0_2/vm_core.h#L1206
|
7
|
+
VM_ENV_DATA_SIZE = 3
|
8
|
+
# Check if Ruby 3.1 or later
|
9
|
+
RICH_AST = begin RubyVM::AbstractSyntaxTree.parse("1", keep_script_lines: true).node_id; true; rescue; false; end
|
10
|
+
end
|
9
11
|
|
10
12
|
FileInfo = Struct.new(
|
11
13
|
:node_id2node,
|
@@ -447,6 +449,11 @@ module TypeProf
|
|
447
449
|
insn.insn, insn.operands = :branch, [:nil] + insn.operands
|
448
450
|
when :getblockparam, :getblockparamproxy
|
449
451
|
insn.insn = :getlocal
|
452
|
+
when :getglobal
|
453
|
+
if insn.operands == [:$typeprof]
|
454
|
+
insn.insn = :putobject
|
455
|
+
insn.operands = [true]
|
456
|
+
end
|
450
457
|
end
|
451
458
|
end
|
452
459
|
end
|
@@ -687,6 +694,27 @@ module TypeProf
|
|
687
694
|
@insns[i + 1] = Insn.new(:getlocal_branch, [getlocal_operands, branch_operands])
|
688
695
|
end
|
689
696
|
end
|
697
|
+
|
698
|
+
# find a pattern: putobject, branch
|
699
|
+
(@insns.size - 1).times do |i|
|
700
|
+
next if branch_targets[i + 1]
|
701
|
+
insn0 = @insns[i]
|
702
|
+
insn1 = @insns[i + 1]
|
703
|
+
if insn0.insn == :putobject && insn1.insn == :branch
|
704
|
+
putobject_operands = insn0.operands
|
705
|
+
branch_operands = insn1.operands
|
706
|
+
obj = putobject_operands[0]
|
707
|
+
branch_type = branch_operands[0]
|
708
|
+
branch_target = branch_operands[1]
|
709
|
+
case branch_type
|
710
|
+
when :if then jump = !!obj
|
711
|
+
when :unless then jump = !obj
|
712
|
+
when :nil then jump = obj == nil
|
713
|
+
end
|
714
|
+
@insns[i ] = Insn.new(:nop, [])
|
715
|
+
@insns[i + 1] = jump ? Insn.new(:jump, [branch_target]) : Insn.new(:nop, [])
|
716
|
+
end
|
717
|
+
end
|
690
718
|
end
|
691
719
|
|
692
720
|
def check_send_branch(sp, j)
|
data/lib/typeprof/type.rb
CHANGED
@@ -59,10 +59,13 @@ module TypeProf
|
|
59
59
|
else
|
60
60
|
if ty2.is_a?(Type::ContainerType)
|
61
61
|
# ty2 may have type variables
|
62
|
-
|
63
|
-
|
62
|
+
if ty1.class == ty2.class
|
63
|
+
ty1.match?(ty2)
|
64
|
+
else
|
65
|
+
Type.match?(ty1, ty2.base_type)
|
66
|
+
end
|
64
67
|
elsif ty1.is_a?(Type::ContainerType)
|
65
|
-
|
68
|
+
Type.match?(ty1.base_type, ty2)
|
66
69
|
else
|
67
70
|
ty1.consistent?(ty2) ? {} : nil
|
68
71
|
end
|
@@ -810,7 +813,9 @@ module TypeProf
|
|
810
813
|
when :$0, :$PROGRAM_NAME
|
811
814
|
Type::Instance.new(Type::Builtin[:str])
|
812
815
|
when :$~
|
813
|
-
|
816
|
+
# optional type is tentatively disabled; it is too conservative
|
817
|
+
#Type.optional(Type::Instance.new(Type::Builtin[:matchdata]))
|
818
|
+
Type::Instance.new(Type::Builtin[:matchdata])
|
814
819
|
when :$., :$$
|
815
820
|
Type::Instance.new(Type::Builtin[:int])
|
816
821
|
when :$?
|
data/lib/typeprof/version.rb
CHANGED
data/lib/typeprof.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typeprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.21.
|
4
|
+
version: 0.21.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yusuke Endoh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rbs
|
@@ -37,6 +37,7 @@ executables:
|
|
37
37
|
extensions: []
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
|
+
- ".github/dependabot.yml"
|
40
41
|
- ".github/workflows/main.yml"
|
41
42
|
- ".gitignore"
|
42
43
|
- Gemfile
|
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
- !ruby/object:Gem::Version
|
89
90
|
version: '0'
|
90
91
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
92
|
+
rubygems_version: 3.5.0.dev
|
92
93
|
signing_key:
|
93
94
|
specification_version: 4
|
94
95
|
summary: TypeProf is a type analysis tool for Ruby code based on abstract interpretation
|