Skip to content

Commit 063eb2b

Browse files
authored
Add RDoc documentation site for Rubydex APIs (#874)
## Problems - Rubydex does not have generated API documentation that can be published as a static site. - The native extension exposes Ruby APIs from C, but most public C-backed methods are not documented in a format RDoc can capture. ## Solutions - Add RDoc configuration, a documentation rake task, and a GitHub Pages workflow using the current RDoc commit. - Include both Ruby and C extension sources in the generated site. - Convert public C-backed API comments to RDoc `call-seq:` blocks with RBS-ish return shapes. <img width="80%" height="1364" alt="Screenshot 2026-06-24 at 21 07 02" src="https://github.com/user-attachments/assets/89d1c023-9c30-41fb-9a7d-493b19be3964" /> (The `workspace_path` attribute's type label is weird but it's a RDoc issue)
1 parent fb82a5f commit 063eb2b

16 files changed

Lines changed: 491 additions & 121 deletions

.document

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
README.md
2+
CONTRIBUTING.md
3+
docs/*.md
4+
lib/**/*.rb
5+
ext/rubydex/*.c

.github/workflows/pages.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Deploy documentation to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: true
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
if: ${{ github.repository == 'Shopify/rubydex' }}
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
24+
25+
- name: Set up Ruby
26+
uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0
27+
with:
28+
bundler-cache: true
29+
30+
- name: Build documentation
31+
run: bundle exec rake rdoc
32+
33+
- name: Upload artifact
34+
uses: actions/upload-pages-artifact@v5.0.0
35+
36+
deploy:
37+
environment:
38+
name: github-pages
39+
url: ${{ steps.deployment.outputs.page_url }}
40+
runs-on: ubuntu-latest
41+
needs: build
42+
steps:
43+
- name: Deploy to GitHub Pages
44+
id: deployment
45+
uses: actions/deploy-pages@v5.0.0

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/.bundle/
22
/.yardoc
33
/_yardoc/
4+
/_site/
45
/coverage/
56
/doc/
67
/pkg/

.rdoc_options

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
op_dir: _site
2+
title: Rubydex
3+
main_page: README.md
4+
5+
footer_content:
6+
DOCUMENTATION:
7+
Home: index.html
8+
RESOURCES:
9+
GitHub Repository: https://github.com/Shopify/rubydex
10+
Issue Tracker: https://github.com/Shopify/rubydex/issues

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ gemspec
88
gem "rake", "~> 13.3"
99
gem "rake-compiler"
1010
gem "minitest"
11+
gem "rdoc"
1112
gem "rubocop"
1213
gem "rubocop-shopify"
1314
gem "extconf_compile_commands_json"

Gemfile.lock

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ GEM
77
remote: https://rubygems.org/
88
specs:
99
ast (2.4.3)
10-
date (3.5.1)
1110
drb (2.2.3)
1211
erb (6.0.4)
1312
extconf_compile_commands_json (0.0.7)
@@ -40,9 +39,6 @@ GEM
4039
prettyprint
4140
prettyprint (0.2.0)
4241
prism (1.9.0)
43-
psych (5.3.1)
44-
date
45-
stringio
4642
racc (1.8.1)
4743
rainbow (3.1.1)
4844
rake (13.3.1)
@@ -52,9 +48,10 @@ GEM
5248
logger
5349
prism (>= 1.6.0)
5450
tsort
55-
rdoc (7.2.0)
51+
rdoc (8.0.0)
5652
erb
57-
psych (>= 4.0.0)
53+
prism (>= 1.6.0)
54+
rbs (>= 4.0.0)
5855
tsort
5956
regexp_parser (2.12.0)
6057
reline (0.6.3)
@@ -78,7 +75,6 @@ GEM
7875
ruby-progressbar (1.13.0)
7976
ruby_memcheck (3.0.1)
8077
nokogiri
81-
stringio (3.2.0)
8278
tsort (0.2.0)
8379
unicode-display_width (3.2.0)
8480
unicode-emoji (~> 4.1)
@@ -96,6 +92,7 @@ DEPENDENCIES
9692
rake (~> 13.3)
9793
rake-compiler
9894
rbs
95+
rdoc
9996
rubocop
10097
rubocop-shopify
10198
ruby_memcheck

Rakefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ require "bundler/gem_tasks"
44
require "rubocop/rake_task"
55
require "rake/extensiontask"
66
require "rake/testtask"
7+
require "rdoc/task"
78

89
GEMSPEC = Gem::Specification.load("rubydex.gemspec")
910

@@ -28,6 +29,10 @@ end
2829

2930
RuboCop::RakeTask.new
3031

32+
RDoc::Task.new do |doc|
33+
doc.rdoc_dir = "_site"
34+
end
35+
3136
task :lint do
3237
puts "******** Linting ********\n"
3338
Rake::Task["rubocop"].invoke

ext/rubydex/declaration.c

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include "rustbindings.h"
66
#include "utils.h"
77

8+
/*
9+
* RDoc parser workaround for https://github.com/ruby/rdoc/issues/1744:
10+
* mRubydex = rb_define_module("Rubydex")
11+
*/
12+
813
VALUE cDeclaration;
914
VALUE cNamespace;
1015
VALUE cClass;
@@ -46,7 +51,12 @@ VALUE rdxi_declaration_class_for_kind(CDeclarationKind kind) {
4651
}
4752
}
4853

49-
// Declaration#name -> String
54+
/*
55+
* call-seq:
56+
* name -> String?
57+
*
58+
* Returns the fully qualified declaration name.
59+
*/
5060
static VALUE rdxr_declaration_name(VALUE self) {
5161
HandleData *data;
5262
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -65,7 +75,12 @@ static VALUE rdxr_declaration_name(VALUE self) {
6575
return str;
6676
}
6777

68-
// Declaration#unqualified_name -> String
78+
/*
79+
* call-seq:
80+
* unqualified_name -> String?
81+
*
82+
* Returns the declaration name without namespace qualification.
83+
*/
6984
static VALUE rdxr_declaration_unqualified_name(VALUE self) {
7085
HandleData *data;
7186
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -126,8 +141,12 @@ static VALUE declaration_definitions_size(VALUE self, VALUE _args, VALUE _eobj)
126141
return SIZET2NUM(len);
127142
}
128143

129-
// Declaration#definitions: () -> Enumerator[Definition]
130-
// Returns an enumerator that yields all definitions for this declaration lazily
144+
/*
145+
* call-seq:
146+
* definitions -> Enumerator[Rubydex::Definition]
147+
*
148+
* Returns an enumerator that yields all definitions for this declaration lazily.
149+
*/
131150
static VALUE rdxr_declaration_definitions(VALUE self) {
132151
if (!rb_block_given_p()) {
133152
return rb_enumeratorize_with_size(self, rb_str_new2("definitions"), 0, NULL, declaration_definitions_size);
@@ -146,8 +165,12 @@ static VALUE rdxr_declaration_definitions(VALUE self) {
146165
return self;
147166
}
148167

149-
// Declaration#member: (String member) -> Declaration
150-
// Returns a declaration handle for the given member
168+
/*
169+
* call-seq:
170+
* member(name) -> Rubydex::Declaration?
171+
*
172+
* Returns a declaration handle for the named member, or nil if no member exists.
173+
*/
151174
static VALUE rdxr_declaration_member(VALUE self, VALUE name) {
152175
HandleData *data;
153176
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -171,8 +194,12 @@ static VALUE rdxr_declaration_member(VALUE self, VALUE name) {
171194
return rb_class_new_instance(2, argv, decl_class);
172195
}
173196

174-
// Namespace#find_member: (String member, only_inherited: false) -> Declaration?
175-
// Searches for a member in the ancestor chain of the declaration
197+
/*
198+
* call-seq:
199+
* find_member(name, only_inherited: false) -> Rubydex::Declaration?
200+
*
201+
* Searches for a member in the declaration's ancestor chain.
202+
*/
176203
static VALUE rdxr_declaration_find_member(int argc, VALUE *argv, VALUE self) {
177204
VALUE member, opts;
178205
rb_scan_args(argc, argv, "1:", &member, &opts);
@@ -207,7 +234,12 @@ static VALUE rdxr_declaration_find_member(int argc, VALUE *argv, VALUE self) {
207234
return rb_class_new_instance(2, result_argv, decl_class);
208235
}
209236

210-
// Declaration#singleton_class -> SingletonClass
237+
/*
238+
* call-seq:
239+
* singleton_class -> Rubydex::SingletonClass?
240+
*
241+
* Returns the singleton class declaration, or nil if none exists.
242+
*/
211243
static VALUE rdxr_declaration_singleton_class(VALUE self) {
212244
HandleData *data;
213245
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -227,7 +259,12 @@ static VALUE rdxr_declaration_singleton_class(VALUE self) {
227259
return rb_class_new_instance(2, argv, decl_class);
228260
}
229261

230-
// Declaration#owner -> Declaration
262+
/*
263+
* call-seq:
264+
* owner -> Rubydex::Declaration
265+
*
266+
* Returns the owner declaration.
267+
*/
231268
static VALUE rdxr_declaration_owner(VALUE self) {
232269
HandleData *data;
233270
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -247,7 +284,12 @@ static VALUE rdxr_declaration_owner(VALUE self) {
247284
return rb_class_new_instance(2, argv, decl_class);
248285
}
249286

250-
// Declaration#ancestors: () -> Enumerator[Declaration]
287+
/*
288+
* call-seq:
289+
* ancestors -> Enumerator[Rubydex::Namespace]
290+
*
291+
* Returns an enumerator that yields ancestor namespaces.
292+
*/
251293
static VALUE rdxr_declaration_ancestors(VALUE self) {
252294
if (!rb_block_given_p()) {
253295
return rb_enumeratorize(self, rb_str_new2("ancestors"), 0, NULL);
@@ -270,7 +312,12 @@ static VALUE rdxr_declaration_ancestors(VALUE self) {
270312
return self;
271313
}
272314

273-
// Declaration#descendants: () -> Enumerator[Declaration]
315+
/*
316+
* call-seq:
317+
* descendants -> Enumerator[Rubydex::Namespace]
318+
*
319+
* Returns an enumerator that yields descendant namespaces.
320+
*/
274321
static VALUE rdxr_declaration_descendants(VALUE self) {
275322
if (!rb_block_given_p()) {
276323
return rb_enumeratorize(self, rb_str_new2("descendants"), 0, NULL);
@@ -293,7 +340,12 @@ static VALUE rdxr_declaration_descendants(VALUE self) {
293340
return self;
294341
}
295342

296-
// Namespace#members: () -> Enumerator[Declaration]
343+
/*
344+
* call-seq:
345+
* members -> Enumerator[Rubydex::Declaration]
346+
*
347+
* Returns an enumerator that yields member declarations.
348+
*/
297349
static VALUE rdxr_declaration_members(VALUE self) {
298350
if (!rb_block_given_p()) {
299351
return rb_enumeratorize(self, rb_str_new2("members"), 0, NULL);
@@ -334,8 +386,12 @@ static VALUE constant_declaration_references_size(VALUE self, VALUE _args, VALUE
334386
return SIZET2NUM(len);
335387
}
336388

337-
// Namespace#references, Constant#references, ConstantAlias#references
338-
// Returns an enumerator that yields constant references to this declaration
389+
/*
390+
* call-seq:
391+
* references -> Enumerator[Rubydex::ConstantReference]
392+
*
393+
* Returns an enumerator that yields constant references to this declaration.
394+
*/
339395
static VALUE rdxr_constant_declaration_references(VALUE self) {
340396
if (!rb_block_given_p()) {
341397
return rb_enumeratorize_with_size(self, rb_str_new2("references"), 0, NULL,
@@ -377,8 +433,12 @@ static VALUE method_declaration_references_size(VALUE self, VALUE _args, VALUE _
377433
return SIZET2NUM(len);
378434
}
379435

380-
// Method#references
381-
// Returns an enumerator that yields method references to this declaration
436+
/*
437+
* call-seq:
438+
* references -> Enumerator[Rubydex::MethodReference]
439+
*
440+
* Returns an enumerator that yields method references to this declaration.
441+
*/
382442
static VALUE rdxr_method_declaration_references(VALUE self) {
383443
if (!rb_block_given_p()) {
384444
return rb_enumeratorize_with_size(self, rb_str_new2("references"), 0, NULL,
@@ -402,7 +462,12 @@ static VALUE rdxr_method_declaration_references(VALUE self) {
402462
return self;
403463
}
404464

405-
// Placeholder for variable declarations that don't yet support references
465+
/*
466+
* call-seq:
467+
* references -> Array[untyped]
468+
*
469+
* Returns an empty array because variable declarations do not yet support reference lookup.
470+
*/
406471
static VALUE rdxr_variable_declaration_references(VALUE self) {
407472
return rb_ary_new();
408473
}
@@ -420,7 +485,12 @@ static VALUE rdxi_visibility_to_symbol(CVisibility visibility) {
420485
}
421486
}
422487

423-
// Declaration#visibility -> Symbol
488+
/*
489+
* call-seq:
490+
* visibility -> Symbol
491+
*
492+
* Returns the declaration visibility.
493+
*/
424494
static VALUE rdxr_declaration_visibility(VALUE self) {
425495
HandleData *data;
426496
TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -439,9 +509,13 @@ static VALUE rdxr_declaration_visibility(VALUE self) {
439509
return symbol;
440510
}
441511

442-
// ConstantAlias#target -> Declaration?
443-
// Returns the first resolved target declaration for this constant alias, or nil if none of its definitions resolved to
444-
// a target
512+
/*
513+
* call-seq:
514+
* target -> Rubydex::Declaration?
515+
*
516+
* Returns the first resolved target declaration for this constant alias, or nil if none of its definitions resolved to
517+
* a target.
518+
*/
445519
static VALUE rdxr_constant_alias_target(VALUE self) {
446520
HandleData *data;
447521
TypedData_Get_Struct(self, HandleData, &handle_type, data);

0 commit comments

Comments
 (0)