rbs 2.0.0 → 2.1.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/.github/workflows/ruby.yml +5 -0
- data/CHANGELOG.md +23 -0
- data/README.md +6 -1
- data/core/array.rbs +2866 -1086
- data/core/basic_object.rbs +150 -30
- data/core/binding.rbs +33 -0
- data/core/builtin.rbs +4 -4
- data/core/class.rbs +43 -5
- data/core/comparable.rbs +57 -0
- data/core/complex.rbs +170 -4
- data/core/constants.rbs +51 -0
- data/core/deprecated.rbs +7 -0
- data/core/dir.rbs +305 -20
- data/core/encoding.rbs +472 -77
- data/core/enumerable.rbs +2173 -234
- data/core/enumerator.rbs +448 -182
- data/core/env.rbs +448 -1
- data/core/errno.rbs +1 -10
- data/core/errors.rbs +152 -2
- data/core/exception.rbs +201 -127
- data/core/false_class.rbs +27 -0
- data/core/fiber.rbs +118 -37
- data/core/fiber_error.rbs +8 -9
- data/core/file.rbs +1059 -139
- data/core/file_test.rbs +287 -32
- data/core/float.rbs +776 -300
- data/core/gc.rbs +185 -34
- data/core/global_variables.rbs +5 -1
- data/core/hash.rbs +1582 -649
- data/core/integer.rbs +974 -204
- data/core/io/buffer.rbs +710 -0
- data/core/io/wait.rbs +29 -8
- data/core/io.rbs +2438 -417
- data/core/kernel.rbs +2315 -316
- data/core/marshal.rbs +37 -2
- data/core/match_data.rbs +123 -6
- data/core/math.rbs +126 -6
- data/core/method.rbs +226 -102
- data/core/module.rbs +421 -45
- data/core/nil_class.rbs +64 -0
- data/core/numeric.rbs +620 -142
- data/core/object.rbs +453 -81
- data/core/object_space.rbs +92 -2
- data/core/proc.rbs +482 -285
- data/core/process.rbs +443 -34
- data/core/ractor.rbs +232 -9
- data/core/random.rbs +151 -52
- data/core/range.rbs +885 -160
- data/core/rational.rbs +122 -6
- data/core/rb_config.rbs +14 -4
- data/core/refinement.rbs +44 -0
- data/core/regexp.rbs +156 -14
- data/core/ruby_vm.rbs +42 -3
- data/core/signal.rbs +78 -39
- data/core/string.rbs +2123 -567
- data/core/string_io.rbs +204 -0
- data/core/struct.rbs +283 -28
- data/core/symbol.rbs +304 -30
- data/core/thread.rbs +1288 -688
- data/core/thread_group.rbs +66 -10
- data/core/time.rbs +643 -217
- data/core/trace_point.rbs +100 -12
- data/core/true_class.rbs +24 -0
- data/core/unbound_method.rbs +73 -7
- data/core/warning.rbs +37 -12
- data/docs/CONTRIBUTING.md +40 -34
- data/docs/stdlib.md +3 -102
- data/lib/rbs/annotate/annotations.rb +197 -0
- data/lib/rbs/annotate/formatter.rb +80 -0
- data/lib/rbs/annotate/rdoc_annotator.rb +398 -0
- data/lib/rbs/annotate/rdoc_source.rb +120 -0
- data/lib/rbs/annotate.rb +6 -0
- data/lib/rbs/cli.rb +45 -1
- data/lib/rbs/definition_builder.rb +5 -1
- data/lib/rbs/location_aux.rb +12 -0
- data/lib/rbs/prototype/rb.rb +12 -0
- data/lib/rbs/version.rb +1 -1
- data/sig/annotate/annotations.rbs +102 -0
- data/sig/annotate/formatter.rbs +24 -0
- data/sig/annotate/rdoc_annotater.rbs +82 -0
- data/sig/annotate/rdoc_source.rbs +30 -0
- data/sig/cli.rbs +2 -0
- data/sig/collection/{collections.rbs → sources.rbs} +0 -0
- data/sig/location.rbs +6 -0
- data/sig/method_types.rbs +5 -1
- data/sig/polyfill.rbs +78 -0
- data/stdlib/abbrev/0/abbrev.rbs +6 -0
- data/stdlib/abbrev/0/array.rbs +26 -0
- data/stdlib/base64/0/base64.rbs +31 -0
- data/stdlib/benchmark/0/benchmark.rbs +74 -3
- data/stdlib/bigdecimal/0/big_decimal.rbs +614 -165
- data/stdlib/bigdecimal-math/0/big_math.rbs +41 -64
- data/stdlib/cgi/0/core.rbs +59 -0
- data/stdlib/coverage/0/coverage.rbs +164 -2
- data/stdlib/csv/0/csv.rbs +2862 -398
- data/stdlib/date/0/date.rbs +483 -25
- data/stdlib/date/0/date_time.rbs +187 -12
- data/stdlib/dbm/0/dbm.rbs +152 -17
- data/stdlib/digest/0/digest.rbs +146 -0
- data/stdlib/erb/0/erb.rbs +65 -245
- data/stdlib/fiber/0/fiber.rbs +73 -91
- data/stdlib/fileutils/0/fileutils.rbs +301 -1
- data/stdlib/find/0/find.rbs +9 -0
- data/stdlib/forwardable/0/forwardable.rbs +65 -1
- data/stdlib/io-console/0/io-console.rbs +227 -15
- data/stdlib/ipaddr/0/ipaddr.rbs +161 -0
- data/stdlib/json/0/json.rbs +1146 -144
- data/stdlib/logger/0/formatter.rbs +24 -0
- data/stdlib/logger/0/log_device.rbs +64 -0
- data/stdlib/logger/0/logger.rbs +165 -13
- data/stdlib/logger/0/period.rbs +10 -0
- data/stdlib/logger/0/severity.rbs +26 -0
- data/stdlib/monitor/0/monitor.rbs +163 -0
- data/stdlib/mutex_m/0/mutex_m.rbs +35 -6
- data/stdlib/net-http/0/net-http.rbs +1492 -683
- data/stdlib/nkf/0/nkf.rbs +372 -0
- data/stdlib/objspace/0/objspace.rbs +149 -90
- data/stdlib/openssl/0/openssl.rbs +8108 -71
- data/stdlib/optparse/0/optparse.rbs +487 -19
- data/stdlib/pathname/0/pathname.rbs +425 -124
- data/stdlib/prettyprint/0/prettyprint.rbs +120 -99
- data/stdlib/prime/0/integer-extension.rbs +20 -2
- data/stdlib/prime/0/prime.rbs +88 -21
- data/stdlib/pstore/0/pstore.rbs +102 -0
- data/stdlib/pty/0/pty.rbs +64 -14
- data/stdlib/resolv/0/resolv.rbs +420 -31
- data/stdlib/rubygems/0/basic_specification.rbs +4 -1
- data/stdlib/rubygems/0/config_file.rbs +33 -1
- data/stdlib/rubygems/0/dependency_installer.rbs +4 -3
- data/stdlib/rubygems/0/installer.rbs +13 -1
- data/stdlib/rubygems/0/path_support.rbs +4 -1
- data/stdlib/rubygems/0/platform.rbs +5 -1
- data/stdlib/rubygems/0/request_set.rbs +44 -2
- data/stdlib/rubygems/0/requirement.rbs +65 -2
- data/stdlib/rubygems/0/rubygems.rbs +407 -0
- data/stdlib/rubygems/0/source_list.rbs +13 -0
- data/stdlib/rubygems/0/specification.rbs +21 -1
- data/stdlib/rubygems/0/stream_ui.rbs +3 -1
- data/stdlib/rubygems/0/uninstaller.rbs +8 -1
- data/stdlib/rubygems/0/version.rbs +60 -157
- data/stdlib/securerandom/0/securerandom.rbs +44 -0
- data/stdlib/set/0/set.rbs +420 -106
- data/stdlib/shellwords/0/shellwords.rbs +55 -77
- data/stdlib/singleton/0/singleton.rbs +20 -0
- data/stdlib/socket/0/addrinfo.rbs +210 -9
- data/stdlib/socket/0/basic_socket.rbs +103 -11
- data/stdlib/socket/0/ip_socket.rbs +31 -9
- data/stdlib/socket/0/socket.rbs +586 -38
- data/stdlib/socket/0/tcp_server.rbs +22 -2
- data/stdlib/socket/0/tcp_socket.rbs +12 -1
- data/stdlib/socket/0/udp_socket.rbs +25 -2
- data/stdlib/socket/0/unix_server.rbs +22 -2
- data/stdlib/socket/0/unix_socket.rbs +45 -5
- data/stdlib/strscan/0/string_scanner.rbs +210 -9
- data/stdlib/tempfile/0/tempfile.rbs +58 -10
- data/stdlib/time/0/time.rbs +208 -116
- data/stdlib/timeout/0/timeout.rbs +10 -0
- data/stdlib/tmpdir/0/tmpdir.rbs +13 -4
- data/stdlib/tsort/0/cyclic.rbs +1 -0
- data/stdlib/tsort/0/interfaces.rbs +1 -0
- data/stdlib/tsort/0/tsort.rbs +42 -0
- data/stdlib/uri/0/common.rbs +57 -8
- data/stdlib/uri/0/file.rbs +55 -109
- data/stdlib/uri/0/ftp.rbs +6 -3
- data/stdlib/uri/0/generic.rbs +556 -327
- data/stdlib/uri/0/http.rbs +26 -115
- data/stdlib/uri/0/https.rbs +8 -102
- data/stdlib/uri/0/ldap.rbs +143 -137
- data/stdlib/uri/0/ldaps.rbs +8 -102
- data/stdlib/uri/0/mailto.rbs +3 -0
- data/stdlib/uri/0/rfc2396_parser.rbs +66 -26
- data/stdlib/uri/0/ws.rbs +6 -3
- data/stdlib/uri/0/wss.rbs +5 -3
- data/stdlib/yaml/0/dbm.rbs +151 -87
- data/stdlib/yaml/0/store.rbs +6 -0
- data/stdlib/zlib/0/zlib.rbs +90 -31
- metadata +17 -5
- data/lib/rbs/location.rb +0 -221
data/docs/stdlib.md
CHANGED
|
@@ -1,109 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Testing Core API and Standard Library Types
|
|
2
2
|
|
|
3
|
-
This is a guide for
|
|
4
|
-
|
|
5
|
-
The typical steps of writing signatures will be like the following:
|
|
6
|
-
|
|
7
|
-
1. Generate a prototype
|
|
8
|
-
2. Import RDoc document
|
|
9
|
-
3. Give correct types to the prototype
|
|
10
|
-
4. Add tests
|
|
11
|
-
|
|
12
|
-
## Signatures
|
|
13
|
-
|
|
14
|
-
Signatures for builtin libraries are located in `core` directory. Also, signatures for standard libraries are located in `stdlib` directory.
|
|
15
|
-
|
|
16
|
-
To write signatures see [syntax guide](syntax.md).
|
|
17
|
-
|
|
18
|
-
## Generating prototypes
|
|
19
|
-
|
|
20
|
-
`rbs` provides a tool to generate a prototype of signatures, `rbs prototype`.
|
|
21
|
-
It provides several options, `rbi` from Sorbet RBI files, `rb` from Ruby code, and `runtime` from runtime API.
|
|
22
|
-
`runtime` should be the best option for standard libraries because they may be implemented in C, no Ruby source code.
|
|
23
|
-
|
|
24
|
-
The tool `require`s all of the libraries specified with `-r` option, and then use introspection APIs like `instance_methods` to know the structure of the class.
|
|
25
|
-
The commandline receives the name of classes you want to prototype, exact class name (like `Pathname`) or pattern with `*` (like `IO::*`).
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
$ bundle exec rbs prototype runtime --require pathname Pathname
|
|
29
|
-
class Pathname
|
|
30
|
-
def self.getwd: () -> untyped
|
|
31
|
-
|
|
32
|
-
def self.glob: (*untyped) -> untyped
|
|
33
|
-
|
|
34
|
-
def self.pwd: () -> untyped
|
|
35
|
-
|
|
36
|
-
def +: (untyped other) -> untyped
|
|
37
|
-
|
|
38
|
-
alias / +
|
|
39
|
-
|
|
40
|
-
def <=>: (untyped) -> untyped
|
|
41
|
-
|
|
42
|
-
# snip
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# snip
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The prototype includes:
|
|
49
|
-
|
|
50
|
-
* Instance method definitions,
|
|
51
|
-
* Singleton method definitions,
|
|
52
|
-
* Includes, and
|
|
53
|
-
* Constants
|
|
54
|
-
|
|
55
|
-
It generate a simple prototype in the sense that all of the types included are `untyped`.
|
|
56
|
-
But it will help you to have an overview of the signatures you are trying to write.
|
|
57
|
-
|
|
58
|
-
### What to do with existing RBS files
|
|
59
|
-
|
|
60
|
-
Generating prototypes will overwrite existing RBS files, which might be undesirable.
|
|
61
|
-
You can try to find missing parts, or you can start from the scratch.
|
|
62
|
-
|
|
63
|
-
One non-trivial but absolutely better solution is to make a tool:
|
|
64
|
-
|
|
65
|
-
1. To load type definitions from existing RBS file, and
|
|
66
|
-
2. Generate prototypes only for missing methods.
|
|
67
|
-
|
|
68
|
-
## Import RDoc document
|
|
69
|
-
|
|
70
|
-
The next step should be importing RDoc documents.
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
$ bin/annotate-with-rdoc stdlib/pathname/0/pathname.rbs
|
|
74
|
-
Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/system...
|
|
75
|
-
Loading store from /Users/soutaro/.rbenv/versions/2.7.0-dev/share/ri/2.7.0/site...
|
|
76
|
-
Opening stdlib/pathname/pathname.rbs...
|
|
77
|
-
Importing documentation for Pathname...
|
|
78
|
-
Processing glob...
|
|
79
|
-
Processing +...
|
|
80
|
-
# snip
|
|
81
|
-
Writing stdlib/pathname/pathname.rbs...
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
The `annotate-with-rdoc` command adds annotations to RBS files.
|
|
85
|
-
|
|
86
|
-
1. Query RDoc documents to annotate classes, modules, methods, and constants,
|
|
87
|
-
2. Put annotations on RBS AST, and
|
|
88
|
-
3. Update the given .RBS files
|
|
89
|
-
|
|
90
|
-
We recommend using the command to annotate the RBS files.
|
|
91
|
-
|
|
92
|
-
## Writing types
|
|
93
|
-
|
|
94
|
-
The next step is to replace `untyped` types in the prototype.
|
|
95
|
-
See [syntax guide](syntax.md) for the detail of the syntax.
|
|
96
|
-
|
|
97
|
-
We can show some of the guides for writing types.
|
|
98
|
-
|
|
99
|
-
1. Use `bool` for truth values, truthy or falsey. More specific types like `TrueClass | FalseClass` may be too strict.
|
|
100
|
-
2. Use `void` if the return value is useless.
|
|
101
|
-
3. Use `nil` instead of `NilClass`.
|
|
102
|
-
4. The most strict types may not be the best types. Use `untyped` if you cannot find the best one.
|
|
3
|
+
This is a guide for testing core/stdlib types.
|
|
103
4
|
|
|
104
5
|
## Add Tests
|
|
105
6
|
|
|
106
|
-
We support writing tests for stdlib signatures.
|
|
7
|
+
We support writing tests for core/stdlib signatures.
|
|
107
8
|
|
|
108
9
|
### Writing tests
|
|
109
10
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
module RBS
|
|
2
|
+
module Annotate
|
|
3
|
+
class Annotations
|
|
4
|
+
class Skip
|
|
5
|
+
attr_reader :annotation, :skip_children
|
|
6
|
+
|
|
7
|
+
def initialize(annotation:, skip_children:)
|
|
8
|
+
@annotation = annotation
|
|
9
|
+
@skip_children = skip_children
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def hash
|
|
13
|
+
self.class.hash ^ annotation.hash ^ skip_children.hash
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ==(other)
|
|
17
|
+
other.is_a?(Skip) &&
|
|
18
|
+
other.skip_children == skip_children &&
|
|
19
|
+
other.annotation == annotation
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
alias eql? ==
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Source
|
|
26
|
+
attr_reader :annotation
|
|
27
|
+
attr_reader :include_source, :skip_source
|
|
28
|
+
|
|
29
|
+
def initialize(annotation:, include: nil, skip: nil)
|
|
30
|
+
@annotation = annotation
|
|
31
|
+
@include_source = include
|
|
32
|
+
@skip_source = skip
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def hash
|
|
36
|
+
self.class.hash ^ annotation.hash ^ include_source.hash ^ skip_source.hash
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ==(other)
|
|
40
|
+
other.is_a?(Source) &&
|
|
41
|
+
other.annotation == annotation &&
|
|
42
|
+
other.include_source == include_source &&
|
|
43
|
+
other.skip_source == skip_source
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Copy
|
|
50
|
+
attr_reader :annotation, :source
|
|
51
|
+
|
|
52
|
+
def initialize(annotation:, source:)
|
|
53
|
+
@annotation = annotation
|
|
54
|
+
@source = source
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def type_name
|
|
58
|
+
name, _ = partition
|
|
59
|
+
name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def method_name
|
|
63
|
+
_, m = partition
|
|
64
|
+
if m
|
|
65
|
+
m[1]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def singleton?
|
|
70
|
+
_, m = partition
|
|
71
|
+
if m
|
|
72
|
+
m[0]
|
|
73
|
+
else
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def hash
|
|
79
|
+
self.class.hash ^ annotation.hash ^ source.hash
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def ==(other)
|
|
83
|
+
other.is_a?(Copy) &&
|
|
84
|
+
other.annotation == annotation &&
|
|
85
|
+
other.source == source
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
alias eql? ==
|
|
89
|
+
|
|
90
|
+
def partition
|
|
91
|
+
case
|
|
92
|
+
when match = source.match(/(?<constant_name>[^#]+)#(?<method_name>.+)/)
|
|
93
|
+
[
|
|
94
|
+
TypeName(match[:constant_name] || raise),
|
|
95
|
+
[
|
|
96
|
+
false,
|
|
97
|
+
(match[:method_name] or raise).to_sym
|
|
98
|
+
]
|
|
99
|
+
]
|
|
100
|
+
when match = source.match(/(?<constant_name>[^#]+)\.(?<method_name>.+)/)
|
|
101
|
+
[
|
|
102
|
+
TypeName(match[:constant_name] || raise),
|
|
103
|
+
[
|
|
104
|
+
true,
|
|
105
|
+
(match[:method_name] or raise).to_sym
|
|
106
|
+
]
|
|
107
|
+
]
|
|
108
|
+
else
|
|
109
|
+
[
|
|
110
|
+
TypeName(source),
|
|
111
|
+
nil
|
|
112
|
+
]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.parse(annotation)
|
|
118
|
+
string = annotation.string
|
|
119
|
+
|
|
120
|
+
case
|
|
121
|
+
when match = string.match(/\Aannotate:rdoc:skip(:all)?\Z/)
|
|
122
|
+
Skip.new(
|
|
123
|
+
annotation: annotation,
|
|
124
|
+
skip_children: string.end_with?(":all")
|
|
125
|
+
)
|
|
126
|
+
when match = string.match(/\Aannotate:rdoc:source:from=(?<path>.+)\Z/)
|
|
127
|
+
Source.new(
|
|
128
|
+
annotation: annotation,
|
|
129
|
+
include: (match[:path] or raise).strip
|
|
130
|
+
)
|
|
131
|
+
when match = string.match(/\Aannotate:rdoc:source:skip=(?<path>.+)\Z/)
|
|
132
|
+
Source.new(
|
|
133
|
+
annotation: annotation,
|
|
134
|
+
skip: (match[:path] or raise).strip
|
|
135
|
+
)
|
|
136
|
+
when match = string.match(/\Aannotate:rdoc:copy:(?<name>.+)\Z/)
|
|
137
|
+
Copy.new(
|
|
138
|
+
annotation: annotation,
|
|
139
|
+
source: (match[:name] or raise).strip
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
attr_reader :items
|
|
145
|
+
|
|
146
|
+
def initialize(items)
|
|
147
|
+
@items = items
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def skip?
|
|
151
|
+
items.any? {|a| a.is_a?(Skip) }
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def skip_all?
|
|
155
|
+
items.any? {|a| a.is_a?(Skip) && a.skip_children }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def copy_annotation
|
|
159
|
+
_ = items.find {|a| a.is_a?(Copy) }
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_path(path)
|
|
163
|
+
# @type var source_items: Array[Source]
|
|
164
|
+
source_items = _ = items.select {|item| item.is_a?(Source) }
|
|
165
|
+
|
|
166
|
+
return true if source_items.empty?
|
|
167
|
+
|
|
168
|
+
result = source_items[0].include_source == nil
|
|
169
|
+
|
|
170
|
+
items.each do |a|
|
|
171
|
+
if a.is_a?(Source)
|
|
172
|
+
if pat = a.include_source
|
|
173
|
+
if test_path_string(pat, path)
|
|
174
|
+
result = true
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
if pat = a.skip_source
|
|
179
|
+
if test_path_string(pat, path)
|
|
180
|
+
result = false
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
result
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_path_string(pattern, string)
|
|
190
|
+
return true if pattern == string
|
|
191
|
+
return true if string.start_with?(pattern + File::SEPARATOR)
|
|
192
|
+
|
|
193
|
+
false
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module RBS
|
|
2
|
+
module Annotate
|
|
3
|
+
class Formatter
|
|
4
|
+
attr_reader :buffer
|
|
5
|
+
|
|
6
|
+
def initialize()
|
|
7
|
+
@buffer = ""
|
|
8
|
+
@pending_separator = nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def <<(s)
|
|
12
|
+
if s
|
|
13
|
+
if s.is_a?(RDoc::Markup::Document)
|
|
14
|
+
s = self.class.translate(s) or raise
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
s.rstrip!
|
|
18
|
+
|
|
19
|
+
unless s.empty?
|
|
20
|
+
if ss = @pending_separator
|
|
21
|
+
buffer << ss
|
|
22
|
+
buffer << "\n"
|
|
23
|
+
@pending_separator = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
buffer << s
|
|
27
|
+
buffer << "\n"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def margin(separator: "")
|
|
35
|
+
unless buffer.empty?
|
|
36
|
+
@pending_separator = separator
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def empty?
|
|
43
|
+
buffer.empty?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def format(newline_at_end:)
|
|
47
|
+
unless buffer.empty?
|
|
48
|
+
if newline_at_end
|
|
49
|
+
buffer.strip + "\n\n"
|
|
50
|
+
else
|
|
51
|
+
buffer.strip + "\n"
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
buffer
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.each_part(doc, &block)
|
|
59
|
+
if block
|
|
60
|
+
if doc.file
|
|
61
|
+
yield doc
|
|
62
|
+
else
|
|
63
|
+
doc.each do |d|
|
|
64
|
+
each_part(d, &block)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
else
|
|
68
|
+
enum_for :each_part, doc
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.translate(doc)
|
|
73
|
+
if doc.file
|
|
74
|
+
formatter = RDoc::Markup::ToMarkdown.new
|
|
75
|
+
doc.accept(formatter).strip.lines.map(&:rstrip).join("\n")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|