sord 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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