tapioca 0.9.1 → 0.9.2
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/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
|