sord 0.9.0 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfebf9f7b35b936d5a448430b99c0aaa79cb13af0183cdf438c9d210b79fcbe4
4
- data.tar.gz: fd5d9f369fbc55d34bac6b3338cb481a3a0a3ed748d47130327f841e5ac3d8a7
3
+ metadata.gz: ca2e726bf2e1ec8e4baa524ae7111296a18068d1a5d63959abc967bcc01b2651
4
+ data.tar.gz: 6e71373e3eb57ed98395aa0ecca42a5da3cd45ae5212712de151230f0cfa0870
5
5
  SHA512:
6
- metadata.gz: 0407ed5b5770dd46c40df84dd40ba598d650a237f5f5a59127c66d30078970b36c803165dccbb9c6057784bee7763031f15d081fb0aabede6d100d5e943acd10
7
- data.tar.gz: '07849f1278d3d40a3230c45293bc23d6c5ab31360f1d43a55ebc04eefc448e80481fc740180a776d6d999193798a30e1aa961a406c77e9f92d998a67ae43c4e2'
6
+ metadata.gz: 04c0bc1d1b2a74d5d428530cfafe9d21686be9d2bfb032379e7a705478f16ba53c027d85736d4f378104bb443d99706feca733ee1d465b2bf59200bfc61dbd70
7
+ data.tar.gz: 11a6fab0f1bd64e0c3b454bfa4c32ec84cc36b9f7dc2d30d726ab950e1091a0a53328b81666d3767adde2b6ff733af46647e4129a747a15f55db9a39227df8e9
data/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
+ ## [0.10.0] - 2019-09-14
7
+ ### Added
8
+ - Comments in RBIs are now converted from YARD into Markdown format, making them
9
+ look much better when viewed in an IDE. (To restore the old behaviour of copying
10
+ the YARD comments verbatim, use the `--keep-original-comments` flag.)
11
+
12
+ ### Changed
13
+ - Parlour 0.8.0 is now being used.
14
+ - References to `self` as a type in YARD docs are now generated as
15
+ `T.self_type`, rather than a fixed self type determined by Sord.
16
+
6
17
  ## [0.9.0] - 2019-08-09
7
18
  ### Added
8
19
  - Add the `--replace-constants-with-untyped` flag, which generates `T.untyped` instead of `SORD_ERROR` constants.
data/README.md CHANGED
@@ -52,8 +52,9 @@ where the maintainer is unwilling to ship type signatures with the gem itself.
52
52
 
53
53
  Sord also takes some flags to alter the generated `.rbi` file:
54
54
 
55
- - `--no-comments`: Generates the `.rbi` file without any comments about
56
- warnings/inferences/errors.
55
+ - `--no-sord-comments`: Generates the `.rbi` file without any Sord comments
56
+ about warnings/inferences/errors. (The original file's comments will still
57
+ be included.)
57
58
  - `--no-regenerate`: By default, Sord will regenerate a repository's YARD
58
59
  docs for you. This option skips regenerating the YARD docs.
59
60
  - `--break-params`: Determines how many parameters are necessary before
@@ -76,22 +77,22 @@ Say we have this file, called `test.rb`:
76
77
  ```ruby
77
78
  module Example
78
79
  class Person
79
- # @param [String] name
80
- # @param [Integer] age
80
+ # @param name [String] The name of the Person to create.
81
+ # @param age [Integer] The age of the Person to create.
81
82
  # @return [Example::Person]
82
83
  def initialize(name, age)
83
84
  @name = name
84
85
  @age = age
85
86
  end
86
87
 
87
- # @return [String] name
88
+ # @return name [String]
88
89
  attr_accessor :name
89
90
 
90
- # @return [Integer] age
91
+ # @return age [Integer]
91
92
  attr_accessor :age
92
93
 
93
- # @param [Array<String>] possible_names
94
- # @param [Array<Integer>] possible_ages
94
+ # @param possible_names [Array<String>] An array of potential names to choose from.
95
+ # @param possible_ages [Array<Integer>] An array of potential ages to choose from.
95
96
  # @return [Example::Person]
96
97
  def self.construct_randomly(possible_names, possible_ages)
97
98
  Person.new(possible_names.sample, possible_ages.sample)
@@ -116,23 +117,27 @@ The `test.rbi` file then contains a complete RBI file for `test.rb`:
116
117
  # typed: strong
117
118
  module Example
118
119
  class Person
120
+ # @param `name` — The name of the Person to create.
121
+ # @param `age` — The age of the Person to create.
119
122
  sig { params(name: String, age: Integer).returns(Example::Person) }
120
123
  def initialize(name, age); end
121
124
 
122
125
  sig { returns(String) }
123
- def name(); end
126
+ def name; end
124
127
 
125
128
  # sord infer - inferred type of parameter "value" as String using getter's return type
126
129
  sig { params(value: String).returns(String) }
127
130
  def name=(value); end
128
131
 
129
132
  sig { returns(Integer) }
130
- def age(); end
133
+ def age; end
131
134
 
132
135
  # sord infer - inferred type of parameter "value" as Integer using getter's return type
133
136
  sig { params(value: Integer).returns(Integer) }
134
137
  def age=(value); end
135
138
 
139
+ # @param `possible_names` — An array of potential names to choose from.
140
+ # @param `possible_ages` — An array of potential ages to choose from.
136
141
  sig { params(possible_names: T::Array[String], possible_ages: T::Array[Integer]).returns(Example::Person) }
137
142
  def self.construct_randomly(possible_names, possible_ages); end
138
143
  end
data/Rakefile CHANGED
@@ -45,7 +45,7 @@ namespace :examples do
45
45
  # Generate sri
46
46
  puts "Generating rbi for #{name}..."
47
47
  if args[:clean]
48
- system("bundle exec sord ../#{name}.rbi --no-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
48
+ system("bundle exec sord ../#{name}.rbi --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
49
49
  else
50
50
  system("bundle exec sord ../#{name}.rbi")
51
51
  end
@@ -70,7 +70,7 @@ namespace :examples do
70
70
  puts "Regenerating rbi file for #{name}..."
71
71
  Bundler.with_clean_env do
72
72
  if args[:clean]
73
- system("bundle exec sord ../#{name}.rbi --no-regenerate --no-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
73
+ system("bundle exec sord ../#{name}.rbi --no-regenerate --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
74
74
  else
75
75
  system("bundle exec sord ../#{name}.rbi --no-regenerate")
76
76
  end
data/exe/sord CHANGED
@@ -11,23 +11,25 @@ default_command :gen
11
11
  command :gen do |c|
12
12
  c.syntax = 'sord gen <output-file> [options]'
13
13
  c.description = 'Generates an RBI file from this directory\'s YARD docs'
14
- c.option '--[no-]comments', 'Controls informational/warning comments in the RBI file'
14
+ c.option '--[no-]sord-comments', 'Controls informational/warning comments in the RBI file'
15
15
  c.option '--[no-]regenerate', 'Controls whether YARD is executed before Sord runs'
16
16
  c.option '--break-params INTEGER', Integer, 'Break params onto their own lines if there are this many'
17
17
  c.option '--replace-errors-with-untyped', 'Uses T.untyped rather than SORD_ERROR_ constants'
18
18
  c.option '--replace-unresolved-with-untyped', 'Uses T.untyped when Sord is unable to resolve a constant'
19
19
  c.option '--exclude-messages STRING', String, 'Blacklists a comma-separated string of log message types'
20
20
  c.option '--include-messages STRING', String, 'Whitelists a comma-separated string of log message types'
21
+ c.option '--keep-original-comments', 'Retains original YARD comments rather than converting them to Markdown'
21
22
 
22
23
  c.action do |args, options|
23
24
  options.default(
24
- comments: true,
25
+ sord_comments: true,
25
26
  regenerate: true,
26
27
  break_params: 4,
27
28
  replace_errors_with_untyped: false,
28
29
  replace_unresolved_with_untyped: false,
29
30
  exclude_messages: nil,
30
31
  include_messages: nil,
32
+ keep_original_comments: false
31
33
  )
32
34
 
33
35
  if args.length != 1
@@ -10,7 +10,7 @@ module Sord
10
10
  @parlour = nil
11
11
  @options = options
12
12
 
13
- options[:comments] = true if options[:comments].nil?
13
+ options[:sord_comments] = true if options[:sord_comments].nil?
14
14
  options[:regenerate] = true if options[:regenerate].nil?
15
15
  options[:replace_errors_with_untyped] ||= false
16
16
  options[:replace_unresolved_with_untyped] ||= false
@@ -38,11 +38,12 @@ module Sord
38
38
 
39
39
  @replace_errors_with_untyped = options[:replace_errors_with_untyped]
40
40
  @replace_unresolved_with_untyped = options[:replace_unresolved_with_untyped]
41
+ @keep_original_comments = options[:keep_original_comments]
41
42
 
42
43
  # Hook the logger so that messages are added as comments to the RBI file
43
44
  Logging.add_hook do |type, msg, item|
44
45
  @current_object.add_comment_to_next_child("sord #{type} - #{msg}")
45
- end if options[:comments]
46
+ end if options[:sord_comments]
46
47
 
47
48
  # Hook the logger so that warnings are collected
48
49
  Logging.add_hook do |type, msg, item|
@@ -88,7 +89,9 @@ module Sord
88
89
  constant_name = constant.to_s.split('::').last
89
90
 
90
91
  # Add the constant to the current object being generated.
91
- @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)")
92
+ @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
93
+ c.add_comments(constant.docstring.all.split("\n"))
94
+ end
92
95
  end
93
96
  end
94
97
 
@@ -158,8 +161,13 @@ module Sord
158
161
  end
159
162
  end
160
163
 
164
+ return_types = getter.tags('return').flat_map(&:types)
165
+ unless return_types.any?
166
+ Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
167
+ next 'T.untyped'
168
+ end
161
169
  inferred_type = TypeConverter.yard_to_sorbet(
162
- getter.tags('return').flat_map(&:types), meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
170
+ return_types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
163
171
 
164
172
  Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type} using getter's return type", meth)
165
173
  inferred_type
@@ -209,7 +217,89 @@ module Sord
209
217
  parameters: parlour_params,
210
218
  returns: returns,
211
219
  class_method: meth.scope == :class
212
- )
220
+ ) do |m|
221
+ if @keep_original_comments
222
+ m.add_comments(meth.docstring.all.split("\n"))
223
+ else
224
+ parser = YARD::Docstring.parser
225
+ parser.parse(meth.docstring.all)
226
+
227
+ docs_array = parser.text.split("\n")
228
+
229
+ # Add @param tags if there are any with names and descriptions.
230
+ params = parser.tags.select { |tag| tag.tag_name == 'param' && tag.is_a?(YARD::Tags::Tag) && !tag.name.nil? }
231
+ # Add a blank line if there's anything before the params.
232
+ docs_array << '' if docs_array.length.positive? && params.length.positive?
233
+ params.each do |param|
234
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive?
235
+ # Output params in the form of:
236
+ # _@param_ `foo` — Lorem ipsum.
237
+ # _@param_ `foo`
238
+ if param.text.nil?
239
+ docs_array << "_@param_ `#{param.name}`"
240
+ else
241
+ docs_array << "_@param_ `#{param.name}` — #{param.text}"
242
+ end
243
+ end
244
+
245
+ # Add @return tags (there could possibly be more than one, despite this not being supported)
246
+ returns = parser.tags.select { |tag| tag.tag_name == 'return' && tag.is_a?(YARD::Tags::Tag) && !tag.text.nil? && tag.text.strip != '' }
247
+ # Add a blank line if there's anything before the returns.
248
+ docs_array << '' if docs_array.length.positive? && returns.length.positive?
249
+ returns.each do |retn|
250
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive?
251
+ # Output returns in the form of:
252
+ # _@return_ — Lorem ipsum.
253
+ docs_array << "_@return_ — #{retn.text}"
254
+ end
255
+
256
+ # Iterate through the @example tags for a given YARD doc and output them in Markdown codeblocks.
257
+ examples = parser.tags.select { |tag| tag.tag_name == 'example' && tag.is_a?(YARD::Tags::Tag) }
258
+ examples.each do |example|
259
+ # Only add a blank line if there's anything before the example.
260
+ docs_array << '' if docs_array.length.positive?
261
+ # Include the example's 'name' if there is one.
262
+ docs_array << example.name unless example.name.nil? || example.name == ""
263
+ docs_array << "```ruby"
264
+ docs_array.concat(example.text.split("\n"))
265
+ docs_array << "```"
266
+ end if examples.length.positive?
267
+
268
+ # Add @note and @deprecated tags.
269
+ notice_tags = parser.tags.select { |tag| ['note', 'deprecated'].include?(tag.tag_name) && tag.is_a?(YARD::Tags::Tag) }
270
+ # Add a blank line if there's anything before the params.
271
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive? && notice_tags.length.positive?
272
+ notice_tags.each do |notice_tag|
273
+ docs_array << '' if docs_array.last != ''
274
+ # Output note/deprecated/see in the form of:
275
+ # _@note_ — Lorem ipsum.
276
+ # _@note_
277
+ if notice_tag.text.nil?
278
+ docs_array << "_@#{notice_tag.tag_name}_"
279
+ else
280
+ docs_array << "_@#{notice_tag.tag_name}_ — #{notice_tag.text}"
281
+ end
282
+ end
283
+
284
+ # Add @see tags.
285
+ see_tags = parser.tags.select { |tag| tag.tag_name == 'see' && tag.is_a?(YARD::Tags::Tag) }
286
+ # Add a blank line if there's anything before the params.
287
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive? && see_tags.length.positive?
288
+ see_tags.each do |see_tag|
289
+ docs_array << '' if docs_array.last != ''
290
+ # Output note/deprecated/see in the form of:
291
+ # _@see_ `B` — Lorem ipsum.
292
+ # _@see_ `B`
293
+ if see_tag.text.nil?
294
+ docs_array << "_@see_ `#{see_tag.name}`"
295
+ else
296
+ docs_array << "_@see_ `#{see_tag.name}` — #{see_tag.text}"
297
+ end
298
+ end
299
+
300
+ m.add_comments(docs_array)
301
+ end
302
+ end
213
303
  end
214
304
  end
215
305
 
@@ -227,6 +317,7 @@ module Sord
227
317
  @current_object = item.type == :class \
228
318
  ? parent.create_class(item.name.to_s, superclass: superclass)
229
319
  : parent.create_module(item.name.to_s)
320
+ @current_object.add_comments(item.docstring.all.split("\n"))
230
321
 
231
322
  add_mixins(item)
232
323
  add_methods(item)
@@ -107,7 +107,7 @@ module Sord
107
107
  when "bool", "Bool", "boolean", "Boolean", "true", "false"
108
108
  "T::Boolean"
109
109
  when 'self'
110
- item.parent.path
110
+ 'T.self_type'
111
111
  when Array
112
112
  # If there's only one element, unwrap it, otherwise allow for a
113
113
  # selection of any of the types
data/lib/sord/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # typed: strong
2
2
  module Sord
3
- VERSION = '0.9.0'
3
+ VERSION = '0.10.0'
4
4
  end
data/sord.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_dependency 'yard'
26
26
  spec.add_dependency 'sorbet-runtime'
27
27
  spec.add_dependency 'commander', '~> 4.4'
28
- spec.add_dependency 'parlour', '~> 0.6.1'
28
+ spec.add_dependency 'parlour', '~> 0.8.0'
29
29
 
30
30
  spec.add_development_dependency "bundler", "~> 2.0"
31
31
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Christiansen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-09 00:00:00.000000000 Z
11
+ date: 2019-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.6.1
61
+ version: 0.8.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.6.1
68
+ version: 0.8.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement