sord 0.8.0 → 0.9.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: a4302b93ba07124b24e91c6db6a2757d2fe148c573f3b86a918c72155e83d0d5
4
- data.tar.gz: 610ce8222970fb4da8f5d01368a21b1aef4067936f6883b2eb5522e567e8fcce
3
+ metadata.gz: bfebf9f7b35b936d5a448430b99c0aaa79cb13af0183cdf438c9d210b79fcbe4
4
+ data.tar.gz: fd5d9f369fbc55d34bac6b3338cb481a3a0a3ed748d47130327f841e5ac3d8a7
5
5
  SHA512:
6
- metadata.gz: 2a3798003e636dc6baba752bbae52718eefb3f43a5562d7fb3659e39d0a0245c39dd10d297433f05df12f60ac102b93a6ad1b71bc0e1fcb2bf3405233dfb834c
7
- data.tar.gz: 0b9a87eea2db2c948006c89c0970175c98471f0e98358a190c17e6c8e064ff59c5849ea73b0081ef6cd09975488884e333b359a44f8d79a8dac78d6f7f461c3e
6
+ metadata.gz: 0407ed5b5770dd46c40df84dd40ba598d650a237f5f5a59127c66d30078970b36c803165dccbb9c6057784bee7763031f15d081fb0aabede6d100d5e943acd10
7
+ data.tar.gz: '07849f1278d3d40a3230c45293bc23d6c5ab31360f1d43a55ebc04eefc448e80481fc740180a776d6d999193798a30e1aa961a406c77e9f92d998a67ae43c4e2'
data/.parlour ADDED
@@ -0,0 +1,7 @@
1
+ output_file: rbi/sord.rbi
2
+
3
+ requires:
4
+ - sord
5
+
6
+ plugins:
7
+ Sord::ParlourPlugin: {}
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ dist: trusty
3
+ before_install:
4
+ - gem install bundler
5
+ rvm:
6
+ - 2.6
data/CHANGELOG.md CHANGED
@@ -3,6 +3,52 @@ 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.9.0] - 2019-08-09
7
+ ### Added
8
+ - Add the `--replace-constants-with-untyped` flag, which generates `T.untyped` instead of `SORD_ERROR` constants.
9
+ - Added an option to clean the `sord_examples` directory when seeding or reseeding.
10
+ - Added a Rake task to typecheck the `sord_examples` directory.
11
+ - Added a `.parlour` file to the project for generating Sord's RBIs.
12
+ - Added CI with Travis.
13
+
14
+ ### Changed
15
+ - Code generation has been broken out into the Parlour gem, and Sord is now a Parlour plugin.
16
+ - Rainbow is now used for coloured output instead of colorize.
17
+ - Duplicate type signatures are no longer generated for inherited methods.
18
+ - The Resolver can now resolve more objects.
19
+ - If a parameter has `nil` as its default, it now has a nilable type.
20
+ - Generation of constants has been improved.
21
+ - Superclass names are now generated as fully-qualified identifiers.
22
+
23
+ ### Fixed
24
+ - Fixed `T::Hash` and `T::Array` syntax being generated incorrectly.
25
+ - Fix a bug where the `--no-comments` or `--no-generate` flags were ignored.
26
+ - Collections of `T.untyped` now have signatures generated correctly.
27
+ - Fix generation of hashes when they are given too few parameters.
28
+ - YARD no longer prints irrelevant error messages when running rake.
29
+
30
+ ## [0.8.0] - 2019-07-07
31
+ ### Added
32
+ - Block types can now be generated using `@yieldparam` and `@yieldreturn`.
33
+ - Long lists of parameters (at least 4) are now broken onto multiple lines. The threshold can be altered with the `--break-params` option.
34
+ - If a constant used is not found, Sord will now attempt to locate it and fully-qualify its name.
35
+ - Add the `--replace-errors-with-untyped` flag; when present, `T.untyped` is used instead of `SORD_ERROR_` constants.
36
+ - Add the `--include/exclude-messages` flags, which can be used to suppress certain log message kinds.
37
+ - Add support for the `Class<...>` generic becoming `T.class_of(...)`. (#44)
38
+ - Add YARD array (`<...>`) and hash (`{... => ...}`) shorthands. (#43)
39
+ - Sord now has an `examples` set of Rake tasks to test Sord on a large number of repos.
40
+ - Sord now bundles an RBI for itself.
41
+
42
+ ### Changed
43
+ - Methods without any YARD documentation are now typed as `T.untyped` rather than `void`.
44
+
45
+ ### Fixed
46
+ - Duck types in the form of setters (`#foo=`) are now interpreted properly.
47
+ - Fix some cases where indentation was incorrect. (#30, #46)
48
+ - Fix `include` and `extend` calls being swapped, and give them proper blank lines.
49
+ - Fix incorrect blank lines inside empty namespaces.
50
+ - Fix a crash when a `@param` has no name given.
51
+
6
52
  ## [0.7.1] - 2019-06-24
7
53
  ### Fixed
8
54
  - Fix bug where `--no-regenerate` flag was ignored.
data/README.md CHANGED
@@ -60,6 +60,7 @@ Sord also takes some flags to alter the generated `.rbi` file:
60
60
  the signature is changed from a single-line to a multi-line block.
61
61
  (Default: 4)
62
62
  - `--replace-errors-with-untyped`: Uses `T.untyped` instead of `SORD_ERROR_*` constants.
63
+ - `--replace-unresolved-with-untyped`: Uses `T.untyped` when Sord is unable to resolve a constant.
63
64
  - `--include-messages` and `--exclude-messages`: Used to filter the logging
64
65
  messages given by Sord. `--include-messages` acts as a whitelist, printing
65
66
  only messages of the specified logging kinds, whereas `--exclude-messages`
data/Rakefile CHANGED
@@ -20,12 +20,12 @@ REPOS = {
20
20
 
21
21
  namespace :examples do
22
22
  require 'fileutils'
23
- require 'colorize'
23
+ require 'rainbow'
24
24
 
25
25
  desc "Clone git repositories and run Sord on them as examples"
26
- task :seed do
26
+ task :seed, [:clean] do |t, args|
27
27
  if File.directory?('sord_examples')
28
- puts 'sord_examples directory already exists, please delete the directory or run a reseed!'.red
28
+ puts Rainbow('sord_examples directory already exists, please delete the directory or run a reseed!').red
29
29
  exit
30
30
  end
31
31
 
@@ -44,35 +44,91 @@ namespace :examples do
44
44
  system('bundle install')
45
45
  # Generate sri
46
46
  puts "Generating rbi for #{name}..."
47
- system("bundle exec sord ../#{name}.rbi")
47
+ if args[:clean]
48
+ system("bundle exec sord ../#{name}.rbi --no-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
49
+ else
50
+ system("bundle exec sord ../#{name}.rbi")
51
+ end
48
52
  puts "#{name}.rbi generated!"
49
53
  FileUtils.cd '..'
50
54
  end
51
55
  end
52
56
 
53
- puts "Seeding complete!".green
57
+ puts Rainbow("Seeding complete!").green
54
58
  end
55
59
 
56
60
  desc 'Regenerate the rbi files in sord_examples.'
57
- task :reseed do
58
- FileUtils.cd 'sord_examples'
61
+ task :reseed, [:clean] do |t, args|
62
+ if Dir.exist?('sord_examples')
63
+ FileUtils.cd 'sord_examples'
64
+ else
65
+ raise Rainbow("The sord_examples directory does not exist. Have you run the seed task?").red.bold
66
+ end
59
67
 
60
68
  REPOS.keys.each do |name|
61
69
  FileUtils.cd name.to_s
62
70
  puts "Regenerating rbi file for #{name}..."
63
71
  Bundler.with_clean_env do
64
- system("bundle exec sord ../#{name}.rbi --no-regenerate")
72
+ if args[:clean]
73
+ system("bundle exec sord ../#{name}.rbi --no-regenerate --no-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
74
+ else
75
+ system("bundle exec sord ../#{name}.rbi --no-regenerate")
76
+ end
65
77
  end
66
78
  FileUtils.cd '..'
67
79
  end
68
80
 
69
- puts "Re-seeding complete!".green
81
+ puts Rainbow("Re-seeding complete!").green
70
82
  end
71
83
 
72
84
  desc 'Delete the sord_examples directory to allow the seeder to run again.'
73
85
  task :reset do
74
86
  FileUtils.rm_rf 'sord_examples' if File.directory?('sord_examples')
75
- puts 'Reset complete.'.green
87
+ puts Rainbow('Reset complete.').green
76
88
  end
77
- end
78
89
 
90
+ desc 'Typecheck each of the sord_examples rbi files.'
91
+ task :typecheck, [:verbose] do |t, args|
92
+ results_hash = {}
93
+ REPOS.each do |name, url|
94
+ Bundler.with_clean_env do
95
+ puts "srb tc sord_examples/#{name}.rbi --ignore sord.rbi 2>&1"
96
+ if args[:verbose]
97
+ output = system("srb tc sord_examples/#{name}.rbi --ignore sord.rbi 2>&1")
98
+ else
99
+ output = `srb tc sord_examples/#{name}.rbi --ignore sord.rbi 2>&1`.split("\n").last
100
+ results_hash[:"#{name}"] = output
101
+ end
102
+ end
103
+ end
104
+
105
+ unless args[:verbose]
106
+ puts Rainbow("Errors").bold
107
+ longest_name = results_hash.keys.map { |name| name.length }.max
108
+
109
+ # Replace all values in results_hash with integer by parsing it.
110
+ results_hash.each do |name, result|
111
+ result.scan(/Errors\: (\d+)/) { |match| result = match.first.to_i }
112
+ results_hash[name] = (result == "No errors! Great job.") ? 0 : result
113
+ end
114
+
115
+ # Print the right-aligned name and the number of errors, with different colors depending on the number of errors.
116
+ results_hash.each do |name, result|
117
+ spaces_needed = longest_name - name.length
118
+ output = "#{' ' * spaces_needed}#{name}: #{result}"
119
+ case result
120
+ when 0..5
121
+ puts Rainbow(output).green.bright
122
+ when 6..25
123
+ puts Rainbow(output).green
124
+ when 26..50
125
+ puts Rainbow(output).red
126
+ else
127
+ puts Rainbow(output).red.bright
128
+ end
129
+ end
130
+ # Report the Total.
131
+ puts Rainbow("#{' ' * (longest_name - 'Total'.length)}Total: #{results_hash.values.inject(0, :+)}").bold
132
+ end
133
+ end
134
+ end
data/exe/sord CHANGED
@@ -15,6 +15,7 @@ command :gen do |c|
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
+ c.option '--replace-unresolved-with-untyped', 'Uses T.untyped when Sord is unable to resolve a constant'
18
19
  c.option '--exclude-messages STRING', String, 'Blacklists a comma-separated string of log message types'
19
20
  c.option '--include-messages STRING', String, 'Whitelists a comma-separated string of log message types'
20
21
 
@@ -24,6 +25,7 @@ command :gen do |c|
24
25
  regenerate: true,
25
26
  break_params: 4,
26
27
  replace_errors_with_untyped: false,
28
+ replace_unresolved_with_untyped: false,
27
29
  exclude_messages: nil,
28
30
  include_messages: nil,
29
31
  )
@@ -33,41 +35,14 @@ command :gen do |c|
33
35
  exit 1
34
36
  end
35
37
 
36
- if options.include_messages && options.exclude_messages
37
- Sord::Logging.error('Please specify only one of --include-messages and --exclude-messages.')
38
- exit 1
39
- elsif options.include_messages
40
- whitelist = options.include_messages.split(',').map { |x| x.downcase.to_sym }
41
- unless Sord::Logging.valid_types?(whitelist)
42
- Sord::Logging.error('Not all types on your --include-messages list are valid.')
43
- Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
44
- exit 1
45
- end
46
- Sord::Logging.enabled_types = whitelist | [:done]
47
- elsif options.exclude_messages
48
- blacklist = options.exclude_messages.split(',').map { |x| x.downcase.to_sym }
49
- unless Sord::Logging.valid_types?(blacklist)
50
- Sord::Logging.error('Not all types on your --include-messages list are valid.')
51
- Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
52
- exit 1
53
- end
54
- Sord::Logging.enabled_types = Sord::Logging::AVAILABLE_TYPES - blacklist
55
- end
56
-
57
- if options.regenerate
58
- begin
59
- Sord::Logging.info('Running YARD...')
60
- Bundler.with_clean_env do
61
- system('bundle exec yard')
62
- end
63
- rescue Errno::ENOENT
64
- Sord::Logging.error('The YARD tool could not be found on your PATH.')
65
- Sord::Logging.error('You may need to run \'gem install yard\'.')
66
- Sord::Logging.error('If documentation has already been generated, pass --no-regenerate to Sord.')
67
- exit 1
68
- end
69
- end
38
+ plugin_options = options.__hash__
39
+ plugin_options[:exclude_options] = plugin_options[:exclude_options]&.split(',')
40
+ plugin_options[:include_options] = plugin_options[:include_options]&.split(',')
70
41
 
71
- Sord::RbiGenerator.new(options.__hash__).run(args.first)
42
+ plugin = Sord::ParlourPlugin.new(plugin_options)
43
+ plugin.parlour = Parlour::RbiGenerator.new(break_params: plugin_options[:break_params])
44
+ plugin.generate(plugin.parlour.root)
45
+
46
+ File.write(args.first, plugin.parlour.rbi)
72
47
  end
73
48
  end
data/lib/sord/logging.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'colorize'
1
+ # typed: true
2
+ require 'rainbow'
2
3
 
3
4
  module Sord
4
5
  # Handles writing logs to stdout and any other classes which request them.
@@ -68,18 +69,17 @@ module Sord
68
69
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
69
70
  # is associated with, if any. This is shown before the log message if it is
70
71
  # specified.
71
- # @param [Integer] indent_level The level at which to indent the code.
72
72
  # @return [void]
73
- def self.generic(kind, header, msg, item, indent_level = 0)
73
+ def self.generic(kind, header, msg, item)
74
74
  return unless enabled_types.include?(kind)
75
75
 
76
76
  if item
77
- puts "#{header} (#{item.path.bold}) #{msg}" unless silent?
77
+ puts "#{header} (#{Rainbow(item.path).bold}) #{msg}" unless silent?
78
78
  else
79
79
  puts "#{header} #{msg}" unless silent?
80
80
  end
81
81
 
82
- invoke_hooks(kind, msg, item, indent_level)
82
+ invoke_hooks(kind, msg, item)
83
83
  end
84
84
 
85
85
  # Print a warning message. This should be used for things which require the
@@ -88,10 +88,9 @@ module Sord
88
88
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
89
89
  # is associated with, if any. This is shown before the log message if it is
90
90
  # specified.
91
- # @param [Integer] indent_level The level at which to indent the code.
92
91
  # @return [void]
93
- def self.warn(msg, item = nil, indent_level = 0)
94
- generic(:warn, '[WARN ]'.yellow, msg, item, indent_level)
92
+ def self.warn(msg, item = nil)
93
+ generic(:warn, Rainbow('[WARN ]').yellow, msg, item)
95
94
  end
96
95
 
97
96
  # Print an info message. This should be used for generic informational
@@ -100,10 +99,9 @@ module Sord
100
99
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
101
100
  # is associated with, if any. This is shown before the log message if it is
102
101
  # specified.
103
- # @param [Integer] indent_level The level at which to indent the code.
104
102
  # @return [void]
105
- def self.info(msg, item = nil, indent_level = 0)
106
- generic(:info, '[INFO ]', msg, item, indent_level)
103
+ def self.info(msg, item = nil)
104
+ generic(:info, '[INFO ]', msg, item)
107
105
  end
108
106
 
109
107
  # Print a duck-typing message. This should be used when the YARD
@@ -113,10 +111,9 @@ module Sord
113
111
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
114
112
  # is associated with, if any. This is shown before the log message if it is
115
113
  # specified.
116
- # @param [Integer] indent_level The level at which to indent the code.
117
114
  # @return [void]
118
- def self.duck(msg, item = nil, indent_level = 0)
119
- generic(:duck, '[DUCK ]'.cyan, msg, item, indent_level)
115
+ def self.duck(msg, item = nil)
116
+ generic(:duck, Rainbow('[DUCK ]').cyan, msg, item)
120
117
  end
121
118
 
122
119
  # Print an error message. This should be used for things which require the
@@ -125,10 +122,9 @@ module Sord
125
122
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
126
123
  # is associated with, if any. This is shown before the log message if it is
127
124
  # specified.
128
- # @param [Integer] indent_level The level at which to indent the code.
129
125
  # @return [void]
130
- def self.error(msg, item = nil, indent_level = 0)
131
- generic(:error, '[ERROR]'.red, msg, item, indent_level)
126
+ def self.error(msg, item = nil)
127
+ generic(:error, Rainbow('[ERROR]').red, msg, item)
132
128
  end
133
129
 
134
130
  # Print an infer message. This should be used when the user should be told
@@ -138,10 +134,9 @@ module Sord
138
134
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
139
135
  # is associated with, if any. This is shown before the log message if it is
140
136
  # specified.
141
- # @param [Integer] indent_level The level at which to indent the code.
142
137
  # @return [void]
143
- def self.infer(msg, item = nil, indent_level = 0)
144
- generic(:infer, '[INFER]'.light_blue, msg, item, indent_level)
138
+ def self.infer(msg, item = nil)
139
+ generic(:infer, Rainbow('[INFER]').blue, msg, item)
145
140
  end
146
141
 
147
142
  # Print an omit message. This should be used as a special type of warning
@@ -151,10 +146,9 @@ module Sord
151
146
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
152
147
  # is associated with, if any. This is shown before the log message if it is
153
148
  # specified.
154
- # @param [Integer] indent_level The level at which to indent the code.
155
149
  # @return [void]
156
- def self.omit(msg, item = nil, indent_level = 0)
157
- generic(:omit, '[OMIT ]'.magenta, msg, item, indent_level)
150
+ def self.omit(msg, item = nil)
151
+ generic(:omit, Rainbow('[OMIT ]').magenta, msg, item)
158
152
  end
159
153
 
160
154
  # Print a done message. This should be used when a process completes
@@ -163,10 +157,9 @@ module Sord
163
157
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
164
158
  # is associated with, if any. This is shown before the log message if it is
165
159
  # specified.
166
- # @param [Integer] indent_level The level at which to indent the code.
167
160
  # @return [void]
168
- def self.done(msg, item = nil, indent_level = 0)
169
- generic(:done, '[DONE ]'.green, msg, item)
161
+ def self.done(msg, item = nil)
162
+ generic(:done, Rainbow('[DONE ]').green, msg, item)
170
163
  end
171
164
 
172
165
  # Invokes all registered hooks on the logger.
@@ -175,11 +168,10 @@ module Sord
175
168
  # @param [YARD::CodeObjects::Base] item The CodeObject which this log
176
169
  # is associated with, if any. This is shown before the log message if it is
177
170
  # specified.
178
- # @param [Integer] indent_level The level at which to indent the code.
179
171
  # @return [void]
180
- def self.invoke_hooks(kind, msg, item, indent_level = 0)
172
+ def self.invoke_hooks(kind, msg, item)
181
173
  @@hooks.each do |hook|
182
- hook.(kind, msg, item, indent_level) rescue nil
174
+ hook.(kind, msg, item) rescue nil
183
175
  end
184
176
  end
185
177
 
@@ -189,7 +181,6 @@ module Sord
189
181
  # @yieldparam [YARD::CodeObjects::Base] item The CodeObject which this log
190
182
  # is associated with, if any. This is shown before the log message if it is
191
183
  # specified.
192
- # @yieldparam [Integer] indent_level The level at which to indent the code.
193
184
  # @yieldreturn [void]
194
185
  # @return [void]
195
186
  def self.add_hook(&blk)
@@ -0,0 +1,63 @@
1
+ # typed: true
2
+ require 'parlour'
3
+
4
+ module Sord
5
+ class ParlourPlugin < Parlour::Plugin
6
+ attr_reader :options
7
+ attr_accessor :parlour
8
+
9
+ def initialize(options)
10
+ @parlour = nil
11
+ @options = options
12
+
13
+ options[:comments] = true if options[:comments].nil?
14
+ options[:regenerate] = true if options[:regenerate].nil?
15
+ options[:replace_errors_with_untyped] ||= false
16
+ options[:replace_unresolved_with_untyped] ||= false
17
+ end
18
+
19
+ def generate(root)
20
+ if options[:include_messages] && options[:exclude_messages]
21
+ Sord::Logging.error('Please specify only one of --include-messages and --exclude-messages.')
22
+ return false
23
+ elsif options[:include_messages]
24
+ whitelist = options[:include_messages].map { |x| x.downcase.to_sym }
25
+ unless Sord::Logging.valid_types?(whitelist)
26
+ Sord::Logging.error('Not all types on your --include-messages list are valid.')
27
+ Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
28
+ return false
29
+ end
30
+ Sord::Logging.enabled_types = whitelist | [:done]
31
+ elsif options[:exclude_messages]
32
+ blacklist = options[:exclude_messages].map { |x| x.downcase.to_sym }
33
+ unless Sord::Logging.valid_types?(blacklist)
34
+ Sord::Logging.error('Not all types on your --include-messages list are valid.')
35
+ Sord::Logging.error("Valid options are: #{Sord::Logging::AVAILABLE_TYPES.map(&:to_s).join(', ')}")
36
+ return false
37
+ end
38
+ Sord::Logging.enabled_types = Sord::Logging::AVAILABLE_TYPES - blacklist
39
+ end
40
+
41
+ if options[:regenerate]
42
+ begin
43
+ Sord::Logging.info('Running YARD...')
44
+ Bundler.with_clean_env do
45
+ system('bundle exec yard')
46
+ end
47
+ rescue Errno::ENOENT
48
+ Sord::Logging.error('The YARD tool could not be found on your PATH.')
49
+ Sord::Logging.error('You may need to run \'gem install yard\'.')
50
+ Sord::Logging.error('If documentation has already been generated, pass --no-regenerate to Sord.')
51
+ return false
52
+ end
53
+ end
54
+
55
+ options[:parlour] = @parlour
56
+ options[:root] = root
57
+
58
+ Sord::RbiGenerator.new(options).run
59
+
60
+ true
61
+ end
62
+ end
63
+ end