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 +4 -4
- data/lib/tapioca/gem/listeners/source_location.rb +8 -1
- data/lib/tapioca/helpers/rbi_helper.rb +26 -5
- data/lib/tapioca/internal.rb +1 -0
- data/lib/tapioca/runtime/trackers/constant_definition.rb +5 -5
- data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +40 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9cda50b7996366aafe00f6b8643f17385088e842c9626c23b922202702d8ee4
|
4
|
+
data.tar.gz: 040d9732ca74f020d475c3965392b63c2b9a525876cfd765b2c21fa0d031df54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
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
|
data/lib/tapioca/internal.rb
CHANGED
@@ -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
|
-
|
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
|
-
.
|
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
|
data/lib/tapioca/version.rb
CHANGED
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.
|
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
|
+
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
|