tapioca 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e53d805bebee7cb1898eb795daebc5c7f586b5dea934a6056dfc2e1037168e83
4
- data.tar.gz: a9baac8cc53cc87f24495961dfe738603900e9818542c722b79211da2aaea84a
3
+ metadata.gz: c9cda50b7996366aafe00f6b8643f17385088e842c9626c23b922202702d8ee4
4
+ data.tar.gz: 040d9732ca74f020d475c3965392b63c2b9a525876cfd765b2c21fa0d031df54
5
5
  SHA512:
6
- metadata.gz: 101e3405eb9fbc011e3ddb8ad33a622c74f18cde1d3b6be204aa7840fc7d1f89b1c61e61585cfe9d26c397e67839d09fcd85671c5c0b92f2c8b78741ee4e5ded
7
- data.tar.gz: 0a7ad144e5860f72158c194de01213809a5294b69eb2a6de12288d827ca574efdc8937c967ec5c578b1a7c429d4f9e29bd5a1ee6738a373cf4cc57ca2ed8163a
6
+ metadata.gz: a7678c337e77326cedb49b06088ec1b24ae9b08f2047f02efc741134dc6a6efe851a702f45e02c571850c1762aca4de134067015aa8f2da06be9aa1cabb2050b
7
+ data.tar.gz: edd3d2148f8c4ee3c04bdc5025502e859f8d726bf38c741d4357a152770608ba639ad420070a8e071a261b4459bb20b7b637a390991877fd757e9d04a3d0d4b7
@@ -45,12 +45,19 @@ module Tapioca
45
45
  path = Pathname.new(file)
46
46
  return unless File.exist?(path)
47
47
 
48
+ # On native extensions, the source location may point to a shared object (.so, .bundle) file, which we cannot
49
+ # use for jump to definition. Only add source comments on Ruby files
50
+ return unless path.extname == ".rb"
51
+
48
52
  path = if path.realpath.to_s.start_with?(gem.full_gem_path)
49
53
  "#{gem.name}-#{gem.version}/#{path.realpath.relative_path_from(gem.full_gem_path)}"
50
54
  else
51
- path.sub("#{Bundler.bundle_path}/gems/", "")
55
+ path.sub("#{Bundler.bundle_path}/gems/", "").to_s
52
56
  end
53
57
 
58
+ # Strip out the RUBY_ROOT prefix, which is different for each user
59
+ path = path.sub(RbConfig::CONFIG["rubylibdir"], "RUBY_ROOT")
60
+
54
61
  node.comments << RBI::Comment.new("") if node.comments.any?
55
62
  node.comments << RBI::Comment.new("source://#{path}:#{line}")
56
63
  end
@@ -93,15 +93,36 @@ module Tapioca
93
93
 
94
94
  sig { params(name: String).returns(T::Boolean) }
95
95
  def valid_method_name?(name)
96
- name == "==" || !(
97
- name.to_sym.inspect.start_with?(':"', ":@", ":$") ||
98
- name.delete_suffix("=").to_sym.inspect.start_with?(':"', ":@", ":$")
99
- )
96
+ # try to parse a method definition with this name
97
+ iseq = RubyVM::InstructionSequence.compile("def #{name}; end", nil, nil, 0, false)
98
+ # pull out the first operation in the instruction sequence and its first argument
99
+ op, arg, _data = iseq.to_a.dig(-1, 0)
100
+ # make sure that the operation is a method definition and the method that was
101
+ # defined has the expected name, for example, for `def !foo; end` we don't get
102
+ # a syntax error but instead get a method defined as `"foo"`
103
+ op == :definemethod && arg == name.to_sym
104
+ rescue SyntaxError
105
+ false
100
106
  end
101
107
 
102
108
  sig { params(name: String).returns(T::Boolean) }
103
109
  def valid_parameter_name?(name)
104
- /^([[:lower:]]|_|[^[[:ascii:]]])([[:alnum:]]|_|[^[[:ascii:]]])*$/.match?(name)
110
+ sentinel_method_name = :sentinel_method_name
111
+ # try to parse a method definition with this name as the name of a
112
+ # keyword parameter. If we use a positional parameter, then parameter names
113
+ # like `&` (and maybe others) will be treated like `def foo(&); end` and will
114
+ # thus be considered valid. Using a required keyword parameter prevents that
115
+ # confusion between Ruby syntax and parameter name.
116
+ iseq = RubyVM::InstructionSequence.compile("def #{sentinel_method_name}(#{name}:); end", nil, nil, 0, false)
117
+ # pull out the first operation in the instruction sequence and its first argument and data
118
+ op, arg, data = iseq.to_a.dig(-1, 0)
119
+ # make sure that:
120
+ # 1. a method was defined, and
121
+ # 2. the method has the expected method name, and
122
+ # 3. the method has a keyword parameter with the expected name
123
+ op == :definemethod && arg == sentinel_method_name && data.dig(11, :keyword, 0) == name.to_sym
124
+ rescue SyntaxError
125
+ false
105
126
  end
106
127
  end
107
128
  end
@@ -34,6 +34,7 @@ require "tapioca/helpers/rbi_helper"
34
34
  require "tapioca/sorbet_ext/fixed_hash_patch"
35
35
  require "tapioca/sorbet_ext/name_patch"
36
36
  require "tapioca/sorbet_ext/generic_name_patch"
37
+ require "tapioca/sorbet_ext/proc_bind_patch"
37
38
  require "tapioca/runtime/generic_type_registry"
38
39
 
39
40
  require "tapioca/helpers/cli_helper"
@@ -25,16 +25,16 @@ module Tapioca
25
25
 
26
26
  key = tp.self
27
27
 
28
- if tp.path == "(eval)"
28
+ path = tp.path
29
+ if File.exist?(path)
30
+ loc = build_constant_location(tp, caller_locations)
31
+ else
29
32
  caller_location = T.must(caller_locations)
30
- .drop_while { |loc| loc.path == "(eval)" }
31
- .first
33
+ .find { |loc| loc.path && File.exist?(loc.path) }
32
34
 
33
35
  next unless caller_location
34
36
 
35
37
  loc = ConstantLocation.new(path: caller_location.absolute_path || "", lineno: caller_location.lineno)
36
- else
37
- loc = build_constant_location(tp, caller_locations)
38
38
  end
39
39
 
40
40
  (@class_files[key] ||= Set.new) << loc
@@ -0,0 +1,40 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module T
5
+ module Types
6
+ module ProcBindPatch
7
+ def initialize(arg_types, returns, bind = T::Private::Methods::ARG_NOT_PROVIDED)
8
+ super(arg_types, returns)
9
+
10
+ unless bind == T::Private::Methods::ARG_NOT_PROVIDED
11
+ @bind = T.let(T::Utils.coerce(bind), T::Types::Base)
12
+ end
13
+ end
14
+
15
+ def name
16
+ name = super
17
+ name = name.sub("T.proc", "T.proc.bind(#{@bind})") unless @bind.nil?
18
+ name
19
+ end
20
+ end
21
+
22
+ Proc.prepend(ProcBindPatch)
23
+ end
24
+ end
25
+
26
+ module T
27
+ module Private
28
+ module Methods
29
+ module ProcBindPatch
30
+ def finalize_proc(decl)
31
+ super
32
+
33
+ T.unsafe(T::Types::Proc).new(decl.params, decl.returns, decl.bind)
34
+ end
35
+ end
36
+
37
+ singleton_class.prepend(ProcBindPatch)
38
+ end
39
+ end
40
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.9.1"
5
+ VERSION = "0.9.2"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2022-07-14 00:00:00.000000000 Z
14
+ date: 2022-07-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -256,6 +256,7 @@ files:
256
256
  - lib/tapioca/sorbet_ext/fixed_hash_patch.rb
257
257
  - lib/tapioca/sorbet_ext/generic_name_patch.rb
258
258
  - lib/tapioca/sorbet_ext/name_patch.rb
259
+ - lib/tapioca/sorbet_ext/proc_bind_patch.rb
259
260
  - lib/tapioca/static/requires_compiler.rb
260
261
  - lib/tapioca/static/symbol_loader.rb
261
262
  - lib/tapioca/static/symbol_table_parser.rb