sord 5.1.0 → 7.0.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: f101fdc3b63cf69bc59fd766ced5222c3e6b02f70f913fcc39085459e32c89de
4
- data.tar.gz: ea8df6949fdef290b13cf082c364138a17224deb127e069fd8a55d8e86de29c4
3
+ metadata.gz: 0cd5e0c9f0db7151e0f04f309f277fecb64ce6aaf2fefdff88f749ce7a6d02d1
4
+ data.tar.gz: 8ef9d26ef5b4e6cf6acc7a6bfa9f46887a07891346e37cdb46b5e48d903c22bd
5
5
  SHA512:
6
- metadata.gz: 9bed3f4e28d753ccf493a63d552f0560267d5a4841ca6208691e557fa84ba719e1c906be765c4ba45d62ad84cbe167766b8b286202727400bcf62bf8e0748a84
7
- data.tar.gz: c51d9041a3de3dd66faf35173c38ce74e89e5dc4054e9cc675c54a871dc35c84a33139e1a18674265d951f759365a66f272badca1306d89c3b7fa7997f87bb3e
6
+ metadata.gz: 5b5dbaa497fe039afcb125a9e7801bdb124ed1e06b2ba0970b3743f9cfad1aa92a982710fa0f2eb5da9647803e8b2e8d6d11e3b236891687eca35c4f16c25626
7
+ data.tar.gz: 3b432c0005c9cc1d00b6ec4c42a52eb8be6e8dc8425e6eb2a168b1c503e6f6df5fa5ea2a2cfb4c3e4fad98de88104e2166f8cda469305ec383719080a7836ffe
@@ -6,7 +6,7 @@ jobs:
6
6
  test:
7
7
  strategy:
8
8
  matrix:
9
- ruby: [2.7, 3.0, 3.1]
9
+ ruby: [3.0, 3.1]
10
10
  continue-on-error: false
11
11
 
12
12
  runs-on: ubuntu-latest
data/CHANGELOG.md CHANGED
@@ -3,6 +3,30 @@ 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
+ ## [7.0.0] - 2025-03-03
7
+ ### Added
8
+ - Messages now show the file and line number that the message originated from. (Thanks @apiology)
9
+ - Sord will now recognise `Class<T, E>` as an equivalent of `Class<T>, Class<E>`, similar to the
10
+ existing behaviour for `Array`. (Thanks @tomoasleep)
11
+
12
+ ### Changed
13
+ - **Breaking change**: Now uses Commander 5.0 to support Ruby 3.3. This increases the minimum
14
+ required Ruby version to 3.0.
15
+ - **Breaking change**: Parlour version has been bumped significantly, from 5.0 to 9.1. This may be
16
+ relevant if you're using other Parlour plugins alongside Sord.
17
+
18
+ ### Fixed
19
+ - Sord now generates correct RBI when heredoc strings are used in constants. (Thanks @apiology)
20
+ - Fixed error when using as a Parlour plugin, but without any custom tags defined. (Thanks
21
+ @dsisnero)
22
+ - Fixed incorrect precedence when union types were nested inside hashes. (Thanks @apiology)
23
+ - Sord now adds `::` when required, to disambiguate nested namespaces from top-level ones. (Thanks
24
+ @sinsoku)
25
+
26
+ ## [6.0.0] - 2023-05-02
27
+ ### Changed
28
+ - **Breaking change**: Now targets RBS 3.0
29
+
6
30
  ## [5.1.0] - 2023-05-22
7
31
  ### Added
8
32
  - Add support for a single `@overload` tag, typically used to describe methods defined outside of
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in sord.gemspec
4
4
  gemspec
5
+
6
+ # Not in gemspec so it doesn't get distributed or depended on by the built gem.
7
+ # Used by resolver tests, to ensure Sord can import bundled RBIs from gems.
8
+ gem 'resolver-test', path: 'spec/resolver-test-gem'
@@ -4,6 +4,7 @@ require 'sord/type_converter'
4
4
  require 'sord/logging'
5
5
  require 'parlour'
6
6
  require 'rainbow'
7
+ require 'parser/current'
7
8
 
8
9
  module Sord
9
10
  # Converts the current working directory's YARD registry into an type
@@ -80,7 +81,6 @@ module Sord
80
81
 
81
82
  # Hook the logger so that warnings are collected
82
83
  Logging.add_hook do |type, msg, item|
83
- # TODO: is it possible to get line numbers here?
84
84
  warnings << [msg, item, 0] if type == :warn
85
85
  end
86
86
  end
@@ -141,7 +141,25 @@ module Sord
141
141
  # Add the constant to the current object being generated.
142
142
  case @mode
143
143
  when :rbi
144
- @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
144
+ # Parse so we can set up constant with correct heredoc syntax
145
+ kwargs = {}
146
+ value_node = Parser::CurrentRuby.parse(constant.value)
147
+ loc = value_node.loc
148
+ if loc.instance_of? Parser::Source::Map::Heredoc
149
+ #
150
+ # heredocs in Ruby come after the full expression is complete. e.g.,
151
+ # puts(>>FOO)
152
+ # bar
153
+ # FOO
154
+ #
155
+ # so if we want to wrap them in a T.let, we need to parse out the expression vs the rest
156
+ kwargs[:heredocs] = constant.value[loc.heredoc_body.begin_pos...loc.heredoc_end.end_pos]
157
+ expression = loc.expression
158
+ value = constant.value[expression.begin_pos...expression.end_pos]
159
+ else
160
+ value = constant.value
161
+ end
162
+ @current_object.create_constant(constant_name, value: "T.let(#{value}, T.untyped)", **kwargs) do |c|
145
163
  c.add_comments(constant.docstring.all.split("\n"))
146
164
  end
147
165
  when :rbs
@@ -582,8 +600,10 @@ module Sord
582
600
  return if @hide_private && item.visibility == :private
583
601
  count_namespace
584
602
 
585
- superclass = nil
586
- superclass = item.superclass.path.to_s if item.type == :class && item.superclass.to_s != "Object"
603
+ if item.type == :class && item.superclass.to_s != "Object"
604
+ prefix = "::" if item.name.to_s == item.superclass.path
605
+ superclass = "#{prefix}#{item.superclass.path}"
606
+ end
587
607
 
588
608
  parent = @current_object
589
609
  @current_object = item.type == :class \
@@ -651,7 +671,13 @@ module Sord
651
671
  Logging.warn("Please edit the file to fix these errors.")
652
672
  Logging.warn("Alternatively, edit your YARD documentation so that your types are valid and re-run Sord.")
653
673
  warnings.each do |(msg, item, _)|
654
- puts " (#{Rainbow(item&.path).bold}) #{msg}"
674
+ message = if item
675
+ (filename, line), = item.files
676
+ " #{Rainbow("(#{item.path}) #{filename}:#{line}:").bold} #{msg}"
677
+ else
678
+ " #{msg}"
679
+ end
680
+ puts message
655
681
  end
656
682
  end
657
683
  rescue
data/lib/sord/logging.rb CHANGED
@@ -74,7 +74,8 @@ module Sord
74
74
  return unless enabled_types.include?(kind)
75
75
 
76
76
  message = if item
77
- "#{header} (#{Rainbow(item.path).bold}) #{msg}"
77
+ (filename, line), = item.files
78
+ "#{header} #{Rainbow("(#{item.path}) #{filename}:#{line}:").bold} #{msg}"
78
79
  else
79
80
  "#{header} #{msg}"
80
81
  end
@@ -80,6 +80,7 @@ module Sord
80
80
  end
81
81
 
82
82
  def add_custom_tags
83
+ return unless options[:tags]
83
84
  return if options[:tags].empty?
84
85
 
85
86
  options[:tags].each do |tag|
data/lib/sord/resolver.rb CHANGED
@@ -22,13 +22,13 @@ module Sord
22
22
  end
23
23
 
24
24
  def self.load_gem_objects(hash)
25
- all_decls = []
25
+ env = RBS::Environment.new
26
26
  begin
27
- RBS::CLI::LibraryOptions.new.loader.load(env: all_decls)
27
+ RBS::CLI::LibraryOptions.new.loader.load(env: env)
28
28
  rescue RBS::Collection::Config::CollectionNotAvailable
29
29
  Sord::Logging.warn("Could not load RBS collection - run rbs collection install for dependencies")
30
30
  end
31
- add_rbs_objects_to_paths(all_decls, hash)
31
+ add_rbs_objects_to_paths(env, hash)
32
32
 
33
33
  gem_paths = Bundler.load.specs.map(&:full_gem_path)
34
34
  gem_paths.each do |path|
@@ -41,13 +41,22 @@ module Sord
41
41
  end
42
42
  end
43
43
 
44
- def self.add_rbs_objects_to_paths(all_decls, names_to_paths, path=[])
44
+ def self.add_rbs_objects_to_paths(env, names_to_paths, path=[])
45
+ case env
46
+ when RBS::Environment
47
+ declarations = env.declarations
48
+ when Array
49
+ declarations = env
50
+ else
51
+ raise TypeError, "env"
52
+ end
53
+
45
54
  klasses = [
46
55
  RBS::AST::Declarations::Module,
47
56
  RBS::AST::Declarations::Class,
48
57
  RBS::AST::Declarations::Constant
49
58
  ]
50
- all_decls.each do |decl|
59
+ declarations.each do |decl|
51
60
  next unless klasses.include?(decl.class)
52
61
  name = decl.name.to_s
53
62
  new_path = path + [name]
@@ -24,7 +24,7 @@ module Sord
24
24
  # Matches valid method names.
25
25
  # From: https://stackoverflow.com/a/4379197/2626000
26
26
  METHOD_NAME_REGEX =
27
- /(?:[a-z_]\w*[?!=]?|\[\]=?|<<|>>|\*\*|[!~+\*\/%&^|-]|[<>]=?|<=>|={2,3}|![=~]|=~)/i
27
+ /(?:[a-z_]\w*[?!=]?|\[\]=?|<<|>>|\*\*|[!~+\*\/%&^|-]|[<>]=?|<=>|={2,3}|![=~]|=~)/i
28
28
 
29
29
  # Match duck types which require the object implement one or more methods,
30
30
  # like '#foo', '#foo & #bar', '#foo&#bar&#baz', and '#foo&#bar&#baz&#foo_bar'.
@@ -76,13 +76,15 @@ module Sord
76
76
  end
77
77
 
78
78
  # Handle hash rockets as separators.
79
- # e.g. Hash<Symbol => String>
79
+ # e.g. Hash<Symbol => String> or Hash<Symbol, String => Integer>
80
80
  if params[character_pointer] == '=' && params[character_pointer + 1] == '>'
81
81
  if current_bracketing_level == 0
82
82
  character_pointer += 1
83
83
  result << buffer.strip
84
84
  buffer = ""
85
- should_buffer = false
85
+ # commas are higher precedence
86
+ result = [result] if result.length > 1
87
+ return [result.first, split_type_parameters(params[character_pointer+1..-1].strip)]
86
88
  end
87
89
  end
88
90
 
@@ -197,8 +199,12 @@ module Sord
197
199
  .map { |x| yard_to_parlour(x, item, config) }
198
200
  if SINGLE_ARG_GENERIC_TYPES.include?(relative_generic_type) && parameters.length > 1
199
201
  Parlour::Types.const_get(relative_generic_type).new(Parlour::Types::Union.new(parameters))
200
- elsif relative_generic_type == 'Class' && parameters.length == 1
201
- Parlour::Types::Class.new(parameters.first)
202
+ elsif relative_generic_type == 'Class'
203
+ if parameters.length == 1
204
+ Parlour::Types::Class.new(parameters.first)
205
+ else
206
+ Parlour::Types::Union.new(parameters.map { |x| Parlour::Types::Class.new(x) })
207
+ end
202
208
  elsif relative_generic_type == 'Hash'
203
209
  if parameters.length == 2
204
210
  Parlour::Types::Hash.new(*parameters)
data/lib/sord/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # typed: strong
2
2
  module Sord
3
- VERSION = '5.1.0'
3
+ VERSION = '7.0.0'
4
4
  end
data/rbi/sord.rbi CHANGED
@@ -1,7 +1,7 @@
1
1
  # typed: strong
2
2
  # typed: strong
3
3
  module Sord
4
- VERSION = T.let('5.0.0', T.untyped)
4
+ VERSION = T.let('7.0.0', T.untyped)
5
5
 
6
6
  # Handles writing logs to stdout and any other classes which request them.
7
7
  module Logging
@@ -178,12 +178,12 @@ module Sord
178
178
  sig { params(hash: T.untyped).returns(T.untyped) }
179
179
  def self.load_gem_objects(hash); end
180
180
 
181
- # sord omit - no YARD type given for "all_decls", using untyped
181
+ # sord omit - no YARD type given for "env", using untyped
182
182
  # sord omit - no YARD type given for "names_to_paths", using untyped
183
183
  # sord omit - no YARD type given for "path", using untyped
184
184
  # sord omit - no YARD return type given, using untyped
185
- sig { params(all_decls: T.untyped, names_to_paths: T.untyped, path: T.untyped).returns(T.untyped) }
186
- def self.add_rbs_objects_to_paths(all_decls, names_to_paths, path = []); end
185
+ sig { params(env: T.untyped, names_to_paths: T.untyped, path: T.untyped).returns(T.untyped) }
186
+ def self.add_rbs_objects_to_paths(env, names_to_paths, path = []); end
187
187
 
188
188
  # sord omit - no YARD type given for "nodes", using untyped
189
189
  # sord omit - no YARD type given for "names_to_paths", using untyped
@@ -253,6 +253,7 @@ module Sord
253
253
  def add_constants(item); end
254
254
 
255
255
  # sord warn - YARD::CodeObjects::NamespaceObject wasn't able to be resolved to a constant in this project
256
+ # sord warn - Parlour::TypedObject wasn't able to be resolved to a constant in this project
256
257
  # Adds comments to an object based on a docstring.
257
258
  #
258
259
  # _@param_ `item`
@@ -415,6 +416,7 @@ module Sord
415
416
  def self.split_type_parameters(params); end
416
417
 
417
418
  # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
419
+ # sord warn - Parlour::Types::Type wasn't able to be resolved to a constant in this project
418
420
  # Converts a YARD type into a Parlour type.
419
421
  #
420
422
  # _@param_ `yard` — The YARD type.
@@ -425,7 +427,9 @@ module Sord
425
427
  sig { params(yard: T.any(T::Boolean, T::Array[T.untyped], String), item: YARD::CodeObjects::Base, config: Configuration).returns(Parlour::Types::Type) }
426
428
  def self.yard_to_parlour(yard, item, config); end
427
429
 
430
+ # sord warn - Parlour::Types::Type wasn't able to be resolved to a constant in this project
428
431
  # sord warn - YARD::CodeObjects::Base wasn't able to be resolved to a constant in this project
432
+ # sord warn - Parlour::Types::Type wasn't able to be resolved to a constant in this project
429
433
  # Handles SORD_ERRORs.
430
434
  #
431
435
  # _@param_ `name`
@@ -445,6 +449,7 @@ module Sord
445
449
  end
446
450
  def self.handle_sord_error(name, log_warning, item, replace_errors_with_untyped); end
447
451
 
452
+ # sord warn - Parlour::Types::Type wasn't able to be resolved to a constant in this project
448
453
  # Given a YARD duck type string, attempts to convert it to one of a list of pre-defined RBS
449
454
  # built-in interfaces.
450
455
  #
data/sord.gemspec CHANGED
@@ -24,9 +24,10 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'yard'
26
26
  spec.add_dependency 'sorbet-runtime'
27
- spec.add_dependency 'commander', '~> 4.5'
28
- spec.add_dependency 'parlour', '~> 5.0'
29
- spec.add_dependency 'rbs', '~> 2.0'
27
+ spec.add_dependency 'commander', '~> 5.0'
28
+ spec.add_dependency "parser"
29
+ spec.add_dependency 'parlour', '~> 9.1'
30
+ spec.add_dependency 'rbs', '~> 3.0'
30
31
 
31
32
  spec.add_development_dependency "bundler", "~> 2.0"
32
33
  spec.add_development_dependency "rake", "~> 13.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: 5.1.0
4
+ version: 7.0.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: 2023-05-22 00:00:00.000000000 Z
11
+ date: 2025-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard
@@ -44,42 +44,56 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4.5'
47
+ version: '5.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '4.5'
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: parser
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: parlour
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '5.0'
75
+ version: '9.1'
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '5.0'
82
+ version: '9.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rbs
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '2.0'
89
+ version: '3.0'
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '2.0'
96
+ version: '3.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement