Skip to content

Commit b8681d6

Browse files
committed
Support rustdoc JSON format v39
The change should be backward compatible: the tests pass on v39 and v33.
1 parent 413dfd4 commit b8681d6

File tree

9 files changed

+49
-21
lines changed

9 files changed

+49
-21
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- Adjust Rustdoc's json parsing for format v39.
6+
37
## v0.4.0
48

59
- Adjust Rustdoc's json parsing for format v26.

lib/yard-rustdoc/parser.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ def parse
4040

4141
methods = inner
4242
.fetch("impls")
43-
.flat_map { |impl_id| @rustdoc_json.dig(impl_id, "inner", "impl", "items") }
43+
.flat_map do |impl_id|
44+
@rustdoc_json.dig(impl_id.to_s, "inner", "impl", "items")
45+
end
4446
.filter_map do |method_id|
45-
method_entry = @rustdoc_json.fetch(method_id)
47+
method_entry = @rustdoc_json.fetch(method_id.to_s)
4648
next unless relevant_entry?(method_entry)
4749

4850
Statements::Method.new(method_entry)

lib/yard-rustdoc/statements.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,13 @@ def name
104104
# Infers the scope (instance vs class) based on the usage of "self" or
105105
# "rb_self" as an arg name.
106106
def scope
107-
arg_names = @rustdoc
108-
.dig("inner", "function", "decl", "inputs")
107+
inputs =
108+
# JSON rustdoc FORMAT_VERSION < 34
109+
@rustdoc.dig("inner", "function", "decl", "inputs") ||
110+
# >= 34
111+
@rustdoc.dig("inner", "function", "sig", "inputs")
112+
113+
arg_names = inputs
109114
.map(&:first)
110115
.slice(0, 2) # Magnus may inject a Ruby handle as arg0, hence we check 2 args
111116

test/integration_test.rb

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,44 @@
33
require "test_helper"
44

55
class IntegrationTest < Minitest::Test
6-
def setup
7-
super
8-
parse_example
6+
SUPPORTED_VERSIONS = ["v33", "v39"].freeze
7+
8+
def self.test(name, &block)
9+
SUPPORTED_VERSIONS.each do |version|
10+
define_method(:"test_#{name}_#{version}") do
11+
parse_example(version)
12+
instance_exec(&block)
13+
end
14+
end
915
end
1016

11-
def test_class_can_be_renamed
17+
test("class_can_be_renamed") do
1218
assert_defined("Example::Renamed")
1319
end
1420

15-
def test_method_can_be_renamed
21+
test("method_can_be_renamed") do
1622
assert_defined("Example::Foo#renamed")
1723
end
1824

19-
def test_only_tagged_code_is_documented
25+
test("only_tagged_code_is_documented") do
2026
assert_defined("Example::Foo.new")
2127
assert_defined("Example::Foo#bar")
2228
assert_defined("Example::SomeEnum")
2329
refute_defined("Example::Foo#secret")
2430
refute_defined("Example::Secret")
2531
end
2632

27-
def test_rb_self_as_first_param_defines_instance_method
33+
test("rb_self_as_first_param_defines_instance_method") do
2834
refute_defined("Example::Foo.with_rb_self")
2935
assert_defined("Example::Foo#with_rb_self")
3036
end
3137

32-
def test_self_and_rb_self_works_with_ruby_arg
38+
test("self_works_with_ruby_arg") do
3339
refute_defined("Example::Foo.with_ruby_and_rb_self")
3440
assert_defined("Example::Foo#with_ruby_and_rb_self")
3541
end
3642

37-
def test_params_are_extracted_from_def
43+
test("params_are_extracted_from_def") do
3844
foo_bar = YARD::Registry.at("Example::Foo#bar")
3945
params = foo_bar.parameters.to_h
4046
expected = {
@@ -50,12 +56,12 @@ def test_params_are_extracted_from_def
5056
assert_equal(expected, params)
5157
end
5258

53-
def test_removes_atyard_tag
59+
test("removes_atyard_tag") do
5460
foobar = YARD::Registry.at("Example::Foo#bar")
5561
refute(foobar.has_tag?("yard"), "@yard tag should be removed")
5662
end
5763

58-
def test_struct_can_be_a_module
64+
test("struct_can_be_a_module") do
5965
not_class = YARD::Registry.at("NotClass")
6066
assert_equal(:module, not_class.type)
6167
end

test/samples/example-ext/Rakefile

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,27 @@ namespace :doc do
1515

1616
desc "Generate Rust documentation as JSON"
1717
task :rustdoc do
18-
target_dir = "tmp"
18+
require "fileutils"
19+
require "json"
20+
1921
ext_name = "example"
22+
nightly = "+nightly"
23+
nightly += "-#{ENV["NIGHTLY_VERSION"]}" if ENV["NIGHTLY_VERSION"]
24+
2025
run(<<~CMD)
21-
cargo +nightly rustdoc \
22-
--target-dir #{target_dir} \
26+
cargo #{nightly} rustdoc \
27+
--target-dir tmp \
2328
-p #{ext_name} \
2429
-- \
2530
-Zunstable-options --output-format json --document-private-items
2631
CMD
2732

33+
rustdoc_path = "tmp/doc/#{ext_name}.json"
34+
version = JSON.load_file(rustdoc_path).fetch("format_version")
35+
36+
FileUtils.mkdir_p("rustdoc")
2837
run("cp #{rustdoc_path} rustdoc.json")
38+
run("cp #{rustdoc_path} rustdoc/v#{version}.json")
2939
end
3040

3141
def run(cmd)

test/samples/example-ext/rustdoc.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/samples/example-ext/rustdoc/v33.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

test/samples/example-ext/rustdoc/v39.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

test/test_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
class Minitest::Test
1010
private
1111

12-
def parse_example
12+
def parse_example(version)
1313
Dir.chdir("test/samples/example-ext") do
14-
parse_file("rustdoc.json")
14+
parse_file("rustdoc/#{version}.json")
1515
end
1616
end
1717

0 commit comments

Comments
 (0)