Skip to content

Commit

Permalink
Merge branch 'master' into quiet_tests_git
Browse files Browse the repository at this point in the history
  • Loading branch information
mame authored May 24, 2024
2 parents 30c1eec + b11af89 commit 1bd41d8
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 40 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
with:
engine: cruby-truffleruby
min_version: 2.7
min_version: 3.0

build:
needs: ruby-versions
Expand All @@ -22,9 +22,12 @@ jobs:
fail-fast: false
matrix:
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
include:
- ruby: "3.3"
rubyopt: "--enable-frozen-string-literal"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand All @@ -35,5 +38,5 @@ jobs:
- run: bundle exec typeprof --version
- name: Run the test suite
run: |
bundle exec rake TESTOPT=-v
bundle exec rake TESTOPT=-v RUBYOPT="${{ matrix.rubyopt }}"
if: ${{ !startsWith(matrix.ruby, 'truffle') }}
6 changes: 4 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
PATH
remote: .
specs:
typeprof (0.21.7)
typeprof (0.21.11)
rbs (>= 1.8.1)

GEM
remote: https://rubygems.org/
specs:
abbrev (0.1.2)
coverage-helpers (1.0.0)
docile (1.4.0)
power_assert (2.0.1)
rake (13.0.1)
rbs (3.0.2)
rbs (3.4.4)
abbrev
simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
Expand Down
37 changes: 33 additions & 4 deletions lib/typeprof/analyzer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,27 @@ def get_class_name(klass)
if klass == Type.any
"???"
else
path = @class_defs[klass.idx].name
class_def = @class_defs[klass.idx]
path = class_def.name
if @namespace
# Find index where namespace and path don't match anymore
i = 0
i += 1 while @namespace[i] && @namespace[i] == path[i]
if path[i]
path[i..].join("::")
parts = path[i..]

# Sometimes stripping off matching parts of the namespace can lead to matching the wrong
# class so we check here and fully qualify in a case of a mismatch
mismatched = (0..i).any? do |j|
search_path = @namespace[0..j] + parts
found = @class_defs.map { |(_, cd)| cd }.find { |cd| cd.name == search_path }
found && found != class_def
end

# Use the full path and add an empty field to cause leading ::
parts = [""] + path if mismatched

parts.join("::")
else
path.last.to_s
end
Expand Down Expand Up @@ -1374,7 +1389,7 @@ def step(ep)
obj, = operands
env, ty = localize_type(Type.guess_literal_type(obj), env, ep)
env = env.push(ty)
when :putstring
when :putstring, :putchilledstring
str, = operands
ty = Type::Literal.new(str, Type::Instance.new(Type::Builtin[:str]))
env = env.push(ty)
Expand Down Expand Up @@ -2137,7 +2152,7 @@ def step(ep)
end
end
return
when :concatarray
when :concatarray, :concattoarray
env, (ary1, ary2) = env.pop(2)
if ary1.is_a?(Type::Local) && ary1.kind == Type::Array
elems1 = get_container_elem_types(env, ep, ary1.id)
Expand All @@ -2156,6 +2171,20 @@ def step(ep)
env, ty = localize_type(ty, env, ep)
env = env.push(ty)
end
when :pushtoarray
num, = operands
env, (ary, ty, *tys) = env.pop(num + 1)
if ary.is_a?(Type::Local) && ary.kind == Type::Array
tys.each {|ty0| ty = ty.union(ty0) }
elems = get_container_elem_types(env, ep, ary.id)
elems = Type::Array::Elements.new([], elems.squash.union(ty))
env = update_container_elem_types(env, ep, ary.id, ary.base_type) { elems }
env = env.push(ary)
else
elems = Type::Array::Elements.new([], Type.any)
env = update_container_elem_types(env, ep, ary.id, ary.base_type) { elems }
env = env.push(ary)
end

when :checktype
kind, = operands
Expand Down
9 changes: 8 additions & 1 deletion lib/typeprof/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,14 @@ def import(explicit = false)
members = cdef[:members]

name = classpath.last
superclass = path_to_klass(superclass) if superclass
if superclass
if superclass == classpath
# Remove the second to last element so that lookup happens in the parent
superclass = superclass.dup
superclass.delete_at(-2)
end
superclass = path_to_klass(superclass)
end
base_klass = path_to_klass(classpath[0..-2])

klass, = @scratch.get_constant(base_klass, name)
Expand Down
3 changes: 3 additions & 0 deletions lib/typeprof/insns-def.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
:putobject=>["VALUE"],
:putspecialobject=>["rb_num_t"],
:putstring=>["VALUE"],
:putchilledstring=>["VALUE"],
:concatstrings=>["rb_num_t"],
:tostring=>[],
:objtostring=>[],
Expand All @@ -32,6 +33,8 @@
:duphash=>["VALUE"],
:expandarray=>["rb_num_t", "rb_num_t"],
:concatarray=>[],
:concattoarray=>[],
:pushtoarray=>["rb_num_t"],
:splatarray=>["VALUE"],
:newhash=>["rb_num_t"],
:newrange=>["rb_num_t"],
Expand Down
22 changes: 9 additions & 13 deletions lib/typeprof/iseq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@ class ISeq
# https://github.com/ruby/ruby/blob/v3_0_2/vm_core.h#L1206
VM_ENV_DATA_SIZE = 3
# Check if Ruby 3.1 or later
RICH_AST = begin
old_verbose = $VERBOSE
$VERBOSE = nil # get rid of warning
RubyVM::AbstractSyntaxTree.parse("1", keep_script_lines: true).node_id
true
rescue
false
ensure
$VERBOSE = old_verbose
end
RICH_AST = begin RubyVM::AbstractSyntaxTree.parse("_", keep_script_lines: true).node_id; true; rescue; false; end
end

FileInfo = Struct.new(
Expand Down Expand Up @@ -285,7 +276,7 @@ def convert_insns(insns, node_ids, file_info)
misc[:def_node_id] = node_id
end
end
ninsns << Insn.new(insn, operands, lineno, code_range, nil)
ninsns << i = Insn.new(insn, operands, lineno, code_range, nil)
else
raise "unknown iseq entry: #{ e }"
end
Expand Down Expand Up @@ -732,7 +723,7 @@ def check_send_branch(sp, j)

case insn.insn
when :putspecialobject, :putnil, :putobject, :duparray, :putstring,
:putself
:putchilledstring, :putself
sp += 1
when :newarray, :newarraykwsplat, :newhash, :concatstrings
len, = operands
Expand Down Expand Up @@ -849,10 +840,15 @@ def check_send_branch(sp, j)
sp -= 1
return nil if sp <= 0
sp += num + (splat ? 1 : 0)
when :concatarray
when :concatarray, :concattoarray
sp -= 2
return nil if sp <= 0
sp += 1
when :pushtoarray
num, = operands
sp -= num + 1
return nil if sp <= 0
sp += 1
when :checktype
sp -= 1
return nil if sp <= 0
Expand Down
25 changes: 15 additions & 10 deletions lib/typeprof/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -734,14 +734,19 @@ def initialize

def []=(k_ty, v_ty)
k_ty.each_child_global do |k_ty|
# This is a temporal hack to mitigate type explosion
k_ty = Type.any if k_ty.is_a?(Type::Array)
k_ty = Type.any if k_ty.is_a?(Type::Hash)

if @map_tys[k_ty]
@map_tys[k_ty] = @map_tys[k_ty].union(v_ty)
if k_ty.is_a?(Type::Union)
# Flatten recursive union
self[k_ty] = v_ty
else
@map_tys[k_ty] = v_ty
# This is a temporal hack to mitigate type explosion
k_ty = Type.any if k_ty.is_a?(Type::Array)
k_ty = Type.any if k_ty.is_a?(Type::Hash)

if @map_tys[k_ty]
@map_tys[k_ty] = @map_tys[k_ty].union(v_ty)
else
@map_tys[k_ty] = v_ty
end
end
end
end
Expand Down Expand Up @@ -856,7 +861,7 @@ class Signature
include Utils::StructuralEquality

def screen_name(iseq, scratch)
fargs_str = "("
fargs_str = +"("
sig_help = {}
add_farg = -> farg, name, help: false, key: sig_help.size do
name = "`#{ name }`" if RBS::Parser::KEYWORDS.key?(name.to_s)
Expand Down Expand Up @@ -912,11 +917,11 @@ def screen_name(iseq, scratch)

fargs_str << ")"

fargs_str = "" if fargs_str == "()"
fargs_str = +"" if fargs_str == "()"

# Dirty Hack: Stop the iteration at most once!
# I'll remove this hack if RBS removes the limitation of nesting blocks
return fargs_str, sig_help if caller_locations.any? {|frame| frame.label == "show_block_signature" }
return fargs_str, sig_help if caller_locations.any? {|frame| frame.label =~ /\bshow_block_signature\z/ }

optional = false
blks = []
Expand Down
2 changes: 1 addition & 1 deletion lib/typeprof/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module TypeProf
VERSION = "0.21.7"
VERSION = "0.21.11"
end
2 changes: 1 addition & 1 deletion smoke/integer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ def foo(x); end
# Classes
class Object
private
def foo: (Integer x) -> nil
def foo: (Integer? x) -> nil
end
14 changes: 14 additions & 0 deletions smoke/rbs-base-namespace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Qux
module Foo
class Bar < ::Foo::Bar
end
end
end
__END__
# Classes
module Qux
module Foo
class Bar < ::Foo::Bar
end
end
end
5 changes: 5 additions & 0 deletions smoke/rbs-base-namespace.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Foo
class Bar
end
end

4 changes: 4 additions & 0 deletions smoke/rbs-matching-superclass.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo
end
__END__
# Classes
7 changes: 7 additions & 0 deletions smoke/rbs-matching-superclass.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo
end

class Bar
class Foo < Foo
end
end
2 changes: 1 addition & 1 deletion smoke/type_var.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
def number?(ty)
%w[integer float].include?(ty).then { puts 1 }
%w[integer float].include?(ty).then { nil }
end
number?('string')

Expand Down
6 changes: 3 additions & 3 deletions test/typeprof/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class CLITest < Test::Unit::TestCase
rb_file = File.join(__dir__, "../../smoke/simple.rb")
rb_files = [rb_file, rb_file]
rbs_files = []
output = StringIO.new("")
output = StringIO.new(+"")
options = {}
options[:show_untyped] = true
options[:show_errors] = true
Expand Down Expand Up @@ -37,7 +37,7 @@ def foo: (Integer n) -> String
rb_file = File.join(__dir__, "../../smoke/any1.rb")
rb_files = [rb_file]
rbs_files = []
output = StringIO.new("")
output = StringIO.new(+"")
options = {}
options[:exclude_untyped] = true
options[:show_untyped] = true
Expand Down Expand Up @@ -67,7 +67,7 @@ class Object
rb_file = File.join(__dir__, "../../smoke/simple.rb")
rb_files = [rb_file]
rbs_files = [["test.rbs", "class Bar < Foo\nend"]]
output = StringIO.new("")
output = StringIO.new(+"")
options = {}
options[:show_untyped] = true
options[:show_errors] = true
Expand Down
2 changes: 1 addition & 1 deletion test/typeprof/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def run(gem_rbs_features: [], **options)

rb_files = [@name]
rbs_files = [@rbs_path].compact
output = StringIO.new("")
output = StringIO.new(+"")
options[:show_untyped] = true unless options.key?(:show_untyped)
options[:show_errors] = true unless options.key?(:show_errors)
options[:show_indicator] = false unless options.key?(:show_indicator)
Expand Down

0 comments on commit 1bd41d8

Please sign in to comment.