tapioca 0.18.0 → 0.19.0
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/README.md +2 -2
- data/lib/tapioca/cli.rb +1 -1
- data/lib/tapioca/dsl/compiler.rb +7 -2
- data/lib/tapioca/dsl/compilers/aasm.rb +4 -1
- data/lib/tapioca/gem/listeners/documentation.rb +94 -0
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +1 -5
- data/lib/tapioca/gem/listeners.rb +1 -1
- data/lib/tapioca/gem/pipeline.rb +2 -1
- data/lib/tapioca/gemfile.rb +0 -16
- data/lib/tapioca/helpers/rbi_helper.rb +7 -0
- data/lib/tapioca/internal.rb +1 -1
- data/lib/tapioca/rbi_ext/model.rb +4 -3
- data/lib/tapioca/runtime/reflection.rb +8 -1
- data/lib/tapioca/static/symbol_loader.rb +13 -5
- data/lib/tapioca/version.rb +1 -1
- metadata +11 -11
- data/lib/tapioca/gem/listeners/yard_doc.rb +0 -110
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1af20de26e446268513156110cac416ce7ba2b35f96f4bb7898960d640aa4333
|
|
4
|
+
data.tar.gz: 4d760ed85be418d9c9dc166d61ea59ccaf312c929bd4930709abc4b946f3876f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1bf6bbf64b782f072a23109ca90cf9c3743b82501bf304badcd97b816583f2fff3ec3574d58df22f05af716d750ba86589074f43a1ee5d3f9e383fdb83c8ee02
|
|
7
|
+
data.tar.gz: a4d066179177ee84ee349bb7a8514d9b2ad8836051b33adc45ca3708948ddc01a002d6d54fd9c42cc0993ca5e30f74a61f5f5ad8a603ef493b50bee0c7d6ef93
|
data/README.md
CHANGED
|
@@ -161,7 +161,7 @@ All operations performed in working directory.
|
|
|
161
161
|
Please review changes and commit them.
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
This will load your application, find all the gems required by it and generate an RBI file for each gem under the `sorbet/rbi/gems` directory for each of those gems. This process will also import signatures that can be found inside each gem sources, and, optionally, any
|
|
164
|
+
This will load your application, find all the gems required by it and generate an RBI file for each gem under the `sorbet/rbi/gems` directory for each of those gems. This process will also import signatures that can be found inside each gem sources, and, optionally, any documentation inside the gem.
|
|
165
165
|
|
|
166
166
|
<!-- START_HELP_COMMAND_GEM -->
|
|
167
167
|
```shell
|
|
@@ -187,7 +187,7 @@ Options:
|
|
|
187
187
|
# Default: {"activesupport" => "false"}
|
|
188
188
|
[--verify], [--no-verify], [--skip-verify] # Verify RBIs are up-to-date
|
|
189
189
|
# Default: false
|
|
190
|
-
[--doc], [--no-doc], [--skip-doc] # Include
|
|
190
|
+
[--doc], [--no-doc], [--skip-doc] # Include documentation from sources when generating RBIs
|
|
191
191
|
# Default: true
|
|
192
192
|
[--loc], [--no-loc], [--skip-loc] # Include comments with source location when generating RBIs
|
|
193
193
|
# Default: true
|
data/lib/tapioca/cli.rb
CHANGED
|
@@ -225,7 +225,7 @@ module Tapioca
|
|
|
225
225
|
default: false
|
|
226
226
|
option :doc,
|
|
227
227
|
type: :boolean,
|
|
228
|
-
desc: "Include
|
|
228
|
+
desc: "Include documentation from sources when generating RBIs",
|
|
229
229
|
default: true
|
|
230
230
|
option :loc,
|
|
231
231
|
type: :boolean,
|
data/lib/tapioca/dsl/compiler.rb
CHANGED
|
@@ -139,11 +139,16 @@ module Tapioca
|
|
|
139
139
|
|
|
140
140
|
#: (RBI::Scope scope, (Method | UnboundMethod) method_def, ?class_method: bool) -> void
|
|
141
141
|
def create_method_from_def(scope, method_def, class_method: false)
|
|
142
|
+
parameters = compile_method_parameters_to_rbi(method_def)
|
|
143
|
+
return_type = compile_method_return_type_to_rbi(method_def)
|
|
144
|
+
type_params = extract_type_parameters(parameters.map(&:type).push(return_type))
|
|
145
|
+
|
|
142
146
|
scope.create_method(
|
|
143
147
|
method_def.name.to_s,
|
|
144
|
-
parameters:
|
|
145
|
-
return_type:
|
|
148
|
+
parameters: parameters,
|
|
149
|
+
return_type: return_type,
|
|
146
150
|
class_method: class_method,
|
|
151
|
+
type_params: type_params,
|
|
147
152
|
)
|
|
148
153
|
end
|
|
149
154
|
|
|
@@ -90,7 +90,10 @@ module Tapioca
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# Create all of the methods for each event
|
|
93
|
-
parameters = [
|
|
93
|
+
parameters = [
|
|
94
|
+
create_rest_param("opts", type: "T.untyped"),
|
|
95
|
+
create_block_param("block", type: "T.nilable(T.proc.void)"),
|
|
96
|
+
]
|
|
94
97
|
state_machine.events.each do |event|
|
|
95
98
|
model.create_method(event.name.to_s, parameters: parameters)
|
|
96
99
|
model.create_method("#{event.name}!", parameters: parameters)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Tapioca
|
|
5
|
+
module Gem
|
|
6
|
+
module Listeners
|
|
7
|
+
class Documentation < Base
|
|
8
|
+
IGNORED_COMMENTS = [
|
|
9
|
+
":doc:",
|
|
10
|
+
":nodoc:",
|
|
11
|
+
"typed:",
|
|
12
|
+
"frozen_string_literal:",
|
|
13
|
+
"encoding:",
|
|
14
|
+
"warn_indent:",
|
|
15
|
+
"shareable_constant_value:",
|
|
16
|
+
"rubocop:",
|
|
17
|
+
"@requires_ancestor:",
|
|
18
|
+
] #: Array[String]
|
|
19
|
+
|
|
20
|
+
#: (Pipeline pipeline, Rubydex::Graph gem_graph) -> void
|
|
21
|
+
def initialize(pipeline, gem_graph)
|
|
22
|
+
super(pipeline)
|
|
23
|
+
|
|
24
|
+
@gem_graph = gem_graph
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
#: (String line) -> bool
|
|
30
|
+
def rbs_comment?(line)
|
|
31
|
+
line.start_with?(": ", "| ")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @override
|
|
35
|
+
#: (ConstNodeAdded event) -> void
|
|
36
|
+
def on_const(event)
|
|
37
|
+
event.node.comments = documentation_comments(event.symbol)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @override
|
|
41
|
+
#: (ScopeNodeAdded event) -> void
|
|
42
|
+
def on_scope(event)
|
|
43
|
+
event.node.comments = documentation_comments(event.symbol)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @override
|
|
47
|
+
#: (MethodNodeAdded event) -> void
|
|
48
|
+
def on_method(event)
|
|
49
|
+
name = if event.constant.singleton_class?
|
|
50
|
+
"#{event.symbol}::<#{event.symbol.split("::").last}>##{event.node.name}()"
|
|
51
|
+
else
|
|
52
|
+
"#{event.symbol}##{event.node.name}()"
|
|
53
|
+
end
|
|
54
|
+
event.node.comments = documentation_comments(name, sigs: event.node.sigs)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#: (String name, ?sigs: Array[RBI::Sig]) -> Array[RBI::Comment]
|
|
58
|
+
def documentation_comments(name, sigs: [])
|
|
59
|
+
declaration = @gem_graph[name]
|
|
60
|
+
# For attr_writer methods (name ending in =), fall back to reader docs
|
|
61
|
+
if declaration.nil? && name.end_with?("=()")
|
|
62
|
+
declaration = @gem_graph[name.delete_suffix("=()") + "()"]
|
|
63
|
+
end
|
|
64
|
+
# For singleton methods (Class::<Class>#method()), fall back to instance method docs.
|
|
65
|
+
# This handles module_function and extend self methods which Rubydex indexes
|
|
66
|
+
# only under the instance method name.
|
|
67
|
+
if declaration.nil? && name.include?("::<")
|
|
68
|
+
declaration = @gem_graph[name.sub(/::<[^>]+>#/, "#")]
|
|
69
|
+
end
|
|
70
|
+
return [] unless declaration
|
|
71
|
+
|
|
72
|
+
comments = declaration.definitions.flat_map(&:comments)
|
|
73
|
+
comments.uniq!
|
|
74
|
+
return [] if comments.empty?
|
|
75
|
+
|
|
76
|
+
lines = comments
|
|
77
|
+
.map { |comment| comment.string.gsub(/^#+ ?/, "") }
|
|
78
|
+
.reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } || rbs_comment?(line) }
|
|
79
|
+
|
|
80
|
+
# Strip leading and trailing blank lines, matching YARD's behavior
|
|
81
|
+
lines = lines.reverse_each.drop_while(&:empty?).reverse_each.drop_while(&:empty?)
|
|
82
|
+
|
|
83
|
+
lines.map! { |line| RBI::Comment.new(line) }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @override
|
|
87
|
+
#: (NodeAdded event) -> bool
|
|
88
|
+
def ignore?(event)
|
|
89
|
+
event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -8,8 +8,6 @@ module Tapioca
|
|
|
8
8
|
include Runtime::Reflection
|
|
9
9
|
include RBIHelper
|
|
10
10
|
|
|
11
|
-
TYPE_PARAMETER_MATCHER = /T\.type_parameter\(:?([[:word:]]+)\)/
|
|
12
|
-
|
|
13
11
|
private
|
|
14
12
|
|
|
15
13
|
# @override
|
|
@@ -42,9 +40,7 @@ module Tapioca
|
|
|
42
40
|
sig.return_type = return_type
|
|
43
41
|
@pipeline.push_symbol(return_type)
|
|
44
42
|
|
|
45
|
-
parameter_types.values.
|
|
46
|
-
sig.type_params << k
|
|
47
|
-
end
|
|
43
|
+
sig.type_params.concat(extract_type_parameters(parameter_types.values.map(&:to_s).push(return_type)))
|
|
48
44
|
|
|
49
45
|
case signature.mode
|
|
50
46
|
when "abstract"
|
|
@@ -14,5 +14,5 @@ require "tapioca/gem/listeners/sorbet_signatures"
|
|
|
14
14
|
require "tapioca/gem/listeners/sorbet_type_variables"
|
|
15
15
|
require "tapioca/gem/listeners/subconstants"
|
|
16
16
|
require "tapioca/gem/listeners/foreign_constants"
|
|
17
|
-
require "tapioca/gem/listeners/
|
|
17
|
+
require "tapioca/gem/listeners/documentation"
|
|
18
18
|
require "tapioca/gem/listeners/source_location"
|
data/lib/tapioca/gem/pipeline.rb
CHANGED
|
@@ -32,6 +32,7 @@ module Tapioca
|
|
|
32
32
|
|
|
33
33
|
@payload_symbols = Static::SymbolLoader.payload_symbols #: Set[String]
|
|
34
34
|
@bootstrap_symbols = load_bootstrap_symbols(@gem) #: Set[String]
|
|
35
|
+
gem_graph = Static::SymbolLoader.graph_from_paths(@gem.files) if include_doc
|
|
35
36
|
|
|
36
37
|
@bootstrap_symbols.each { |symbol| push_symbol(symbol) }
|
|
37
38
|
|
|
@@ -46,7 +47,7 @@ module Tapioca
|
|
|
46
47
|
@node_listeners << Gem::Listeners::SorbetRequiredAncestors.new(self)
|
|
47
48
|
@node_listeners << Gem::Listeners::SorbetSignatures.new(self)
|
|
48
49
|
@node_listeners << Gem::Listeners::Subconstants.new(self)
|
|
49
|
-
@node_listeners << Gem::Listeners::
|
|
50
|
+
@node_listeners << Gem::Listeners::Documentation.new(self, gem_graph) if include_doc
|
|
50
51
|
@node_listeners << Gem::Listeners::ForeignConstants.new(self)
|
|
51
52
|
@node_listeners << Gem::Listeners::SourceLocation.new(self) if include_loc
|
|
52
53
|
@node_listeners << Gem::Listeners::RemoveEmptyPayloadScopes.new(self)
|
data/lib/tapioca/gemfile.rb
CHANGED
|
@@ -177,22 +177,6 @@ module Tapioca
|
|
|
177
177
|
end
|
|
178
178
|
end
|
|
179
179
|
|
|
180
|
-
#: -> void
|
|
181
|
-
def parse_yard_docs
|
|
182
|
-
files.each do |path|
|
|
183
|
-
YARD.parse(path.to_s, [], Logger::Severity::FATAL)
|
|
184
|
-
rescue RangeError
|
|
185
|
-
# In some circumstances, YARD will raise an error when parsing a file
|
|
186
|
-
# that is actually valid Ruby. We don't want tapioca to halt in these
|
|
187
|
-
# cases, so we'll rescue the error, pretend like there was no
|
|
188
|
-
# documentation, and move on.
|
|
189
|
-
#
|
|
190
|
-
# This can be removed when https://github.com/lsegal/yard/issues/1536
|
|
191
|
-
# is resolved and released.
|
|
192
|
-
[]
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
180
|
#: -> Array[String]
|
|
197
181
|
def exported_rbi_files
|
|
198
182
|
@exported_rbi_files ||= Dir.glob("#{full_gem_path}/rbi/**/*.rbi").sort
|
|
@@ -94,6 +94,13 @@ module Tapioca
|
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
+
TYPE_PARAMETER_MATCHER = /T\.type_parameter\(:?([[:word:]]+)\)/
|
|
98
|
+
|
|
99
|
+
#: (Array[String] type_strings) -> Array[String]
|
|
100
|
+
def extract_type_parameters(type_strings)
|
|
101
|
+
type_strings.join(", ").scan(TYPE_PARAMETER_MATCHER).flatten.uniq
|
|
102
|
+
end
|
|
103
|
+
|
|
97
104
|
#: (String name) -> bool
|
|
98
105
|
def valid_method_name?(name)
|
|
99
106
|
Prism.parse_success?("def self.#{name}(a); end")
|
data/lib/tapioca/internal.rb
CHANGED
|
@@ -65,10 +65,11 @@ module RBI
|
|
|
65
65
|
#| ?return_type: String?,
|
|
66
66
|
#| ?class_method: bool,
|
|
67
67
|
#| ?visibility: RBI::Visibility,
|
|
68
|
-
#| ?comments: Array[RBI::Comment]
|
|
68
|
+
#| ?comments: Array[RBI::Comment],
|
|
69
|
+
#| ?type_params: Array[String]
|
|
69
70
|
#| ) ?{ (RBI::Method node) -> void } -> void
|
|
70
71
|
def create_method(name, parameters: [], return_type: nil, class_method: false, visibility: RBI::Public.new,
|
|
71
|
-
comments: [], &block)
|
|
72
|
+
comments: [], type_params: [], &block)
|
|
72
73
|
return unless Tapioca::RBIHelper.valid_method_name?(name)
|
|
73
74
|
|
|
74
75
|
sigs = []
|
|
@@ -77,7 +78,7 @@ module RBI
|
|
|
77
78
|
# If there is no block, and the params and return type have not been supplied, then
|
|
78
79
|
# we create a single signature with the given parameters and return type
|
|
79
80
|
params = parameters.map { |param| RBI::SigParam.new(param.param.name.to_s, param.type) }
|
|
80
|
-
sigs << RBI::Sig.new(params: params, return_type: return_type || "T.untyped")
|
|
81
|
+
sigs << RBI::Sig.new(params: params, return_type: return_type || "T.untyped", type_params: type_params)
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
method = RBI::Method.new(
|
|
@@ -213,9 +213,16 @@ module Tapioca
|
|
|
213
213
|
|
|
214
214
|
#: (T::Module[top] constant) -> Set[String]
|
|
215
215
|
def file_candidates_for(constant)
|
|
216
|
-
|
|
216
|
+
# Grab all source files for (relevant) methods defined on the constant
|
|
217
|
+
candidates = relevant_methods_for(constant).filter_map do |method|
|
|
217
218
|
method.source_location&.first
|
|
218
219
|
end.to_set
|
|
220
|
+
|
|
221
|
+
# Add the source file for the constant definition itself, if available.
|
|
222
|
+
source_location_candidate = const_source_location(name_of(constant).to_s)&.file
|
|
223
|
+
candidates.add(source_location_candidate) if source_location_candidate
|
|
224
|
+
|
|
225
|
+
candidates
|
|
219
226
|
end
|
|
220
227
|
|
|
221
228
|
#: (T::Module[top] constant) -> untyped
|
|
@@ -18,6 +18,19 @@ module Tapioca
|
|
|
18
18
|
T.must(@payload_symbols)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
#: (Array[Pathname] paths) -> Rubydex::Graph
|
|
22
|
+
def graph_from_paths(paths)
|
|
23
|
+
graph = Rubydex::Graph.new
|
|
24
|
+
graph.index_all(paths.map(&:to_s))
|
|
25
|
+
graph.resolve
|
|
26
|
+
graph
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#: (Gemfile::GemSpec gem) -> Set[String]
|
|
30
|
+
def gem_symbols(gem)
|
|
31
|
+
symbols_from_paths(gem.files)
|
|
32
|
+
end
|
|
33
|
+
|
|
21
34
|
#: (Gemfile::GemSpec gem) -> Set[String]
|
|
22
35
|
def engine_symbols(gem)
|
|
23
36
|
gem_engine = engines.find do |engine|
|
|
@@ -43,11 +56,6 @@ module Tapioca
|
|
|
43
56
|
Set.new
|
|
44
57
|
end
|
|
45
58
|
|
|
46
|
-
#: (Gemfile::GemSpec gem) -> Set[String]
|
|
47
|
-
def gem_symbols(gem)
|
|
48
|
-
symbols_from_paths(gem.files)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
59
|
#: (Array[Pathname] paths) -> Set[String]
|
|
52
60
|
def symbols_from_paths(paths)
|
|
53
61
|
return Set.new if paths.empty?
|
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.
|
|
4
|
+
version: 0.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ufuk Kayserilioglu
|
|
@@ -83,47 +83,47 @@ dependencies:
|
|
|
83
83
|
- !ruby/object:Gem::Version
|
|
84
84
|
version: 0.2.2
|
|
85
85
|
- !ruby/object:Gem::Dependency
|
|
86
|
-
name:
|
|
86
|
+
name: rubydex
|
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
|
88
88
|
requirements:
|
|
89
89
|
- - ">="
|
|
90
90
|
- !ruby/object:Gem::Version
|
|
91
|
-
version: 0.
|
|
91
|
+
version: 0.1.0.beta10
|
|
92
92
|
type: :runtime
|
|
93
93
|
prerelease: false
|
|
94
94
|
version_requirements: !ruby/object:Gem::Requirement
|
|
95
95
|
requirements:
|
|
96
96
|
- - ">="
|
|
97
97
|
- !ruby/object:Gem::Version
|
|
98
|
-
version: 0.
|
|
98
|
+
version: 0.1.0.beta10
|
|
99
99
|
- !ruby/object:Gem::Dependency
|
|
100
|
-
name:
|
|
100
|
+
name: sorbet-static-and-runtime
|
|
101
101
|
requirement: !ruby/object:Gem::Requirement
|
|
102
102
|
requirements:
|
|
103
103
|
- - ">="
|
|
104
104
|
- !ruby/object:Gem::Version
|
|
105
|
-
version:
|
|
105
|
+
version: 0.5.11087
|
|
106
106
|
type: :runtime
|
|
107
107
|
prerelease: false
|
|
108
108
|
version_requirements: !ruby/object:Gem::Requirement
|
|
109
109
|
requirements:
|
|
110
110
|
- - ">="
|
|
111
111
|
- !ruby/object:Gem::Version
|
|
112
|
-
version:
|
|
112
|
+
version: 0.5.11087
|
|
113
113
|
- !ruby/object:Gem::Dependency
|
|
114
|
-
name:
|
|
114
|
+
name: thor
|
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
|
116
116
|
requirements:
|
|
117
117
|
- - ">="
|
|
118
118
|
- !ruby/object:Gem::Version
|
|
119
|
-
version:
|
|
119
|
+
version: 1.2.0
|
|
120
120
|
type: :runtime
|
|
121
121
|
prerelease: false
|
|
122
122
|
version_requirements: !ruby/object:Gem::Requirement
|
|
123
123
|
requirements:
|
|
124
124
|
- - ">="
|
|
125
125
|
- !ruby/object:Gem::Version
|
|
126
|
-
version:
|
|
126
|
+
version: 1.2.0
|
|
127
127
|
- !ruby/object:Gem::Dependency
|
|
128
128
|
name: rbi
|
|
129
129
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -253,6 +253,7 @@ files:
|
|
|
253
253
|
- lib/tapioca/gem/events.rb
|
|
254
254
|
- lib/tapioca/gem/listeners.rb
|
|
255
255
|
- lib/tapioca/gem/listeners/base.rb
|
|
256
|
+
- lib/tapioca/gem/listeners/documentation.rb
|
|
256
257
|
- lib/tapioca/gem/listeners/dynamic_mixins.rb
|
|
257
258
|
- lib/tapioca/gem/listeners/foreign_constants.rb
|
|
258
259
|
- lib/tapioca/gem/listeners/methods.rb
|
|
@@ -266,7 +267,6 @@ files:
|
|
|
266
267
|
- lib/tapioca/gem/listeners/sorbet_type_variables.rb
|
|
267
268
|
- lib/tapioca/gem/listeners/source_location.rb
|
|
268
269
|
- lib/tapioca/gem/listeners/subconstants.rb
|
|
269
|
-
- lib/tapioca/gem/listeners/yard_doc.rb
|
|
270
270
|
- lib/tapioca/gem/pipeline.rb
|
|
271
271
|
- lib/tapioca/gem_info.rb
|
|
272
272
|
- lib/tapioca/gemfile.rb
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
module Tapioca
|
|
5
|
-
module Gem
|
|
6
|
-
module Listeners
|
|
7
|
-
class YardDoc < Base
|
|
8
|
-
IGNORED_COMMENTS = [
|
|
9
|
-
":doc:",
|
|
10
|
-
":nodoc:",
|
|
11
|
-
"typed:",
|
|
12
|
-
"frozen_string_literal:",
|
|
13
|
-
"encoding:",
|
|
14
|
-
"warn_indent:",
|
|
15
|
-
"shareable_constant_value:",
|
|
16
|
-
"rubocop:",
|
|
17
|
-
"@requires_ancestor:",
|
|
18
|
-
] #: Array[String]
|
|
19
|
-
|
|
20
|
-
IGNORED_SIG_TAGS = ["param", "return"] #: Array[String]
|
|
21
|
-
|
|
22
|
-
#: (Pipeline pipeline) -> void
|
|
23
|
-
def initialize(pipeline)
|
|
24
|
-
YARD::Registry.clear
|
|
25
|
-
super(pipeline)
|
|
26
|
-
pipeline.gem.parse_yard_docs
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
#: (String line) -> bool
|
|
32
|
-
def rbs_comment?(line)
|
|
33
|
-
line.start_with?(": ", "| ")
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# @override
|
|
37
|
-
#: (ConstNodeAdded event) -> void
|
|
38
|
-
def on_const(event)
|
|
39
|
-
event.node.comments = documentation_comments(event.symbol)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# @override
|
|
43
|
-
#: (ScopeNodeAdded event) -> void
|
|
44
|
-
def on_scope(event)
|
|
45
|
-
event.node.comments = documentation_comments(event.symbol)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# @override
|
|
49
|
-
#: (MethodNodeAdded event) -> void
|
|
50
|
-
def on_method(event)
|
|
51
|
-
separator = event.constant.singleton_class? ? "." : "#"
|
|
52
|
-
event.node.comments = documentation_comments(
|
|
53
|
-
"#{event.symbol}#{separator}#{event.node.name}",
|
|
54
|
-
sigs: event.node.sigs,
|
|
55
|
-
)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
#: (String name, ?sigs: Array[RBI::Sig]) -> Array[RBI::Comment]
|
|
59
|
-
def documentation_comments(name, sigs: [])
|
|
60
|
-
yard_docs = YARD::Registry.at(name)
|
|
61
|
-
return [] unless yard_docs
|
|
62
|
-
|
|
63
|
-
docstring = yard_docs.docstring
|
|
64
|
-
return [] if /(copyright|license)/i.match?(docstring)
|
|
65
|
-
|
|
66
|
-
comments = docstring.lines
|
|
67
|
-
.reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } || rbs_comment?(line) }
|
|
68
|
-
.map! { |line| RBI::Comment.new(line) }
|
|
69
|
-
|
|
70
|
-
tags = yard_docs.tags
|
|
71
|
-
tags.reject! { |tag| IGNORED_SIG_TAGS.include?(tag.tag_name) } unless sigs.empty?
|
|
72
|
-
|
|
73
|
-
comments << RBI::Comment.new("") if comments.any? && tags.any?
|
|
74
|
-
|
|
75
|
-
tags.sort_by { |tag| [tag.tag_name, tag.name.to_s] }.each do |tag|
|
|
76
|
-
line = +"@#{tag.tag_name}"
|
|
77
|
-
|
|
78
|
-
tag_name = tag.name
|
|
79
|
-
line << " #{tag_name}" if tag_name
|
|
80
|
-
|
|
81
|
-
tag_types = tag.types
|
|
82
|
-
line << " [#{tag_types.join(", ")}]" if tag_types&.any?
|
|
83
|
-
|
|
84
|
-
tag_text = tag.text
|
|
85
|
-
if tag_text && !tag_text.empty?
|
|
86
|
-
text_lines = tag_text.lines
|
|
87
|
-
|
|
88
|
-
# Example are a special case because we want the text to start on the next line
|
|
89
|
-
line << " #{text_lines.shift&.strip}" unless tag.tag_name == "example"
|
|
90
|
-
|
|
91
|
-
text_lines.each do |text_line|
|
|
92
|
-
line << "\n #{text_line.strip}"
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
comments << RBI::Comment.new(line)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
comments
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# @override
|
|
103
|
-
#: (NodeAdded event) -> bool
|
|
104
|
-
def ignore?(event)
|
|
105
|
-
event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|