Skip to content

Commit c17dec3

Browse files
committed
Updated the config options and modified the unit test accordingly. Updated documentation to include parameters for the fuctions.
1 parent 997320b commit c17dec3

File tree

7 files changed

+86
-31
lines changed

7 files changed

+86
-31
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ You can update these by searching for “Rust Doc String Generator” or "rustdo
7272
"rustdocstring.inludeSafetyDetails": false
7373
```
7474

75+
---
76+
7577
## How It Works
7678

7779
RustDocString uses a signature parser (`utils.js`) to scan for the next Rust item and normalize its declaration. Then, depending on the item type:

src/docgen.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
const { generateFunctionDoc } = require('./gen_fn_doc.js');
22
const { generateStructDoc } = require('./gen_struct_doc.js');
33
const { generateEnumDoc } = require('./gen_enum_doc.js');
4-
const vscode = require('vscode');
54

65
/**
76
* Dispatcher for generating Rust doc comments based on the type of code item.
87
* Supports functions, structs, enums, and traits. Delegates to specialized handlers.
98
*
109
* @param {string} line - The normalized line of Rust code (a signature).
10+
* @param {Object} options - Configuration options for doc generation.
11+
* @param {boolean} [options.includeExamples=true] - Whether to include the `# Examples` section.
12+
* @param {boolean} [options.examplesOnlyForPublicOrExtern=false] - Whether to include examples only for `pub` or `extern` items.
13+
* @param {boolean} [options.includeSafetyDetails=false] - Whether to include extended safety guidance in the `# Safety` section.
1114
* @returns {string|null} - The formatted doc comment, or null if unsupported.
1215
*/
13-
function generateDocComment(line) {
14-
const config = vscode.workspace.getConfiguration('rustdocstring');
15-
const includeExamples = config.get('includeExamples', true);
16-
const examplesOnlyForPublicOrExtern = config.get('examplesOnlyForPublicOrExtern', false);
17-
const includeSafetyDetails = config.get('includeSafetyDetails', false);
16+
function generateDocComment(line, options) {
17+
const {
18+
includeExamples = true,
19+
examplesOnlyForPublicOrExtern = false,
20+
includeSafetyDetails = false
21+
} = options;
1822

1923
const itemType = getRustItemType(line);
2024
if (!itemType) return null;

src/extension.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@ function activate(context) {
99
if (!line.trim().endsWith('///')) return;
1010

1111
const signature = findNextSignatureBlock(document, position.line);
12+
const config = vscode.workspace.getConfiguration('rustdocstring');
13+
const includeExamples = config.get('includeExamples', true);
14+
const examplesOnlyForPublicOrExtern = config.get('examplesOnlyForPublicOrExtern', false);
15+
const includeSafetyDetails = config.get('includeSafetyDetails', false);
1216

1317
if (signature) {
14-
const doc = generateDocComment(signature);
18+
const doc = generateDocComment(signature, {
19+
includeExamples,
20+
examplesOnlyForPublicOrExtern,
21+
includeSafetyDetails
22+
});
1523
if (!doc) return;
1624
const item = new vscode.CompletionItem("Generate Rust Doc Comment");
1725
item.insertText = new vscode.SnippetString(doc);

src/gen_enum_doc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Supports unit variants, tuple variants, and struct variants.
1010
*
1111
* @param {string} line - The line containing the Rust `enum` declaration with its body.
12+
* @param {boolean} [includeExamples=true] - Whether to include the `# Examples` section.
13+
* @param {boolean} [examplesOnlyForPublicOrExtern=false] - If true, include examples only for `pub` or `extern` functions.
1214
* @returns {string|null} A formatted doc comment block or null if parsing fails.
1315
*/
1416
function generateEnumDoc(line, includeExamples, examplesOnlyForPublicOrExtern) {

src/gen_fn_doc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
* Tab stops (e.g., `${2:...}`) are included to support editor snippet expansion.
1414
*
1515
* @param {string} line - The normalized function signature, stripped of leading comments or extra lines.
16+
* @param {boolean} [includeExamples=true] - Whether to include the `# Examples` section.
17+
* @param {boolean} [examplesOnlyForPublicOrExtern=false] - If true, include examples only for `pub` or `extern` functions.
18+
* @param {boolean} [includeSafetyDetails=false] - Whether to include extended safety rationale in the `# Safety` section.
1619
* @returns {string|null} The formatted Rust doc comment block as a string, or `null` if the input is not a valid function signature.
1720
*/
1821
function generateFunctionDoc(line, includeExamples, examplesOnlyForPublicOrExtern, includeSafetyDetails) {

src/gen_struct_doc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* Tab stops (`${n:...}`) are inserted for editor snippet expansion.
1717
*
1818
* @param {string} line - A string containing the full struct declaration, including its body.
19+
* @param {boolean} [includeExamples=true] - Whether to include the `# Examples` section.
20+
* @param {boolean} [examplesOnlyForPublicOrExtern=false] - If true, include examples only for `pub` or `extern` functions.
1921
* @returns {string|null} The formatted doc comment block, or `null` if the input is not a valid documentable struct.
2022
*/
2123
function generateStructDoc(line, includeExamples, examplesOnlyForPublicOrExtern) {

src/test/extension.test.js

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ const { findNextSignatureBlock } = require('../utils');
88
describe('generateDocComment()', () => {
99
it('generates doc for function', () => {
1010
const input = 'pub fn compute_sum(a: i32, b: i32) -> i32 {';
11-
const output = generateDocComment(input);
11+
const output = generateDocComment(input, {
12+
includeExamples: true,
13+
examplesOnlyForPublicOrExtern: false,
14+
includeSafetyDetails: true
15+
});
1216
assert.ok(output.includes('# Arguments'));
1317
assert.ok(output.includes('`a` (`i32`)'));
1418
assert.ok(output.includes('# Returns'));
@@ -17,28 +21,40 @@ describe('generateDocComment()', () => {
1721

1822
it('generates doc for struct', () => {
1923
const input = 'pub struct Point { x: f64, y: f64 }';
20-
const output = generateDocComment(input);
24+
const output = generateDocComment(input, {
25+
includeExamples: true,
26+
examplesOnlyForPublicOrExtern: false,
27+
includeSafetyDetails: true
28+
});
2129
assert.ok(output.includes('# Fields'));
2230
assert.ok(output.includes('`x` (`f64`)'));
2331
assert.ok(output.includes('`y` (`f64`)'));
2432
});
2533

2634
it('generates doc for enum', () => {
2735
const input = 'enum Color { Red, Green, Blue }';
28-
const output = generateDocComment(input);
36+
const output = generateDocComment(input, {
37+
includeExamples: true,
38+
examplesOnlyForPublicOrExtern: false,
39+
includeSafetyDetails: true
40+
});
2941
assert.ok(output.includes('# Variants'));
3042
assert.ok(output.includes('`Red`'));
3143
});
3244

3345
it('returns null for unsupported input', () => {
34-
assert.strictEqual(generateDocComment('trait SomeTrait {}'), null);
46+
assert.strictEqual(generateDocComment('trait SomeTrait {}', {
47+
includeExamples: true,
48+
examplesOnlyForPublicOrExtern: false,
49+
includeSafetyDetails: true
50+
}), null);
3551
});
3652
});
3753

3854
describe('generateFunctionDoc()', () => {
3955
it('includes async/unsafe modifiers in example block', () => {
4056
const input = 'pub async unsafe fn risky_call() -> Result<(), Box<dyn Error>> {';
41-
const doc = generateFunctionDoc(input);
57+
const doc = generateFunctionDoc(input, true, true, true);
4258
assert.ok(doc.includes('async {'));
4359
assert.ok(doc.includes('unsafe {'));
4460
assert.ok(doc.includes('# Safety'));
@@ -47,14 +63,14 @@ describe('generateFunctionDoc()', () => {
4763

4864
it('handles simple function without return', () => {
4965
const input = 'fn hello(name: &str) {';
50-
const doc = generateFunctionDoc(input);
66+
const doc = generateFunctionDoc(input, true, true, true);
5167
assert.ok(doc.includes('`name` (`&str`)'));
5268
assert.ok(!doc.includes('# Returns'));
5369
});
5470

5571
it('includes arguments and return section', () => {
5672
const input = 'pub fn add(a: i32, b: i32) -> i32 {';
57-
const output = generateFunctionDoc(input);
73+
const output = generateFunctionDoc(input, true, true, true);
5874
assert.ok(output.includes('# Arguments'), 'Missing arguments section');
5975
assert.ok(output.includes('`a` (`i32`)'));
6076
assert.ok(output.includes('`b` (`i32`)'));
@@ -64,74 +80,92 @@ describe('generateFunctionDoc()', () => {
6480

6581
it('handles unsafe functions', () => {
6682
const input = 'pub unsafe fn access_raw(ptr: *const u8) -> u8 {';
67-
const output = generateFunctionDoc(input);
83+
const output = generateFunctionDoc(input, true, true, true);
6884
assert.ok(output.includes('# Safety'), 'Missing safety section');
6985
assert.ok(output.includes('**This function is `unsafe` because:**'));
7086
assert.ok(output.includes('Describe unsafe behavior'), 'Missing unsafe placeholder');
7187
});
7288

7389
it('handles extern functions', () => {
7490
const input = 'pub extern "C" fn c_func(x: i32) -> i32 {';
75-
const output = generateFunctionDoc(input);
91+
const output = generateFunctionDoc(input, true, true, true);
7692
assert.ok(output.includes('# Safety'), 'Missing safety section');
7793
assert.ok(output.includes('called in the correct program state to avoid UB'), 'Missing UB safety line');
7894
});
7995

8096
it('handles async functions', () => {
8197
const input = 'pub async fn fetch_data() -> Result<String, Box<dyn Error>> {';
82-
const output = generateFunctionDoc(input);
98+
const output = generateFunctionDoc(input, true, true, true);
8399
assert.ok(output.includes('# Errors'), 'Missing errors section');
84100
assert.ok(output.includes('fetch_data().await'), 'Missing async example');
85101
});
86102

87103
it('handles async unsafe extern functions', () => {
88104
const input = 'pub async unsafe extern "C" fn full_danger() -> Result<(), MyError> {';
89-
const output = generateFunctionDoc(input);
105+
const output = generateFunctionDoc(input, true, true, true);
90106
assert.ok(output.includes('# Safety'), 'Missing safety section');
91107
assert.ok(output.includes('unsafe { full_danger().await }'), 'Missing async unsafe example');
92108
assert.ok(output.includes('# Errors'), 'Missing errors section');
93109
});
94110

95111
it('returns null on invalid input', () => {
96-
const output = generateFunctionDoc('this is not a function');
112+
const output = generateFunctionDoc('this is not a function', true, true, true);
97113
assert.strictEqual(output, null);
98114
});
99115

100116
it('handles pub(crate) visibility', () => {
101117
const input = 'pub(crate) fn public_function_in_crate() {';
102-
const doc = generateFunctionDoc(input);
118+
const doc = generateFunctionDoc(input, true, true, true);
103119
assert.ok(doc.includes('Describe this function'), 'Missing main description');
104120
assert.ok(doc.includes('# Examples'), 'Missing example section');
105121
});
106122

107123
it('handles pub(in crate::testing) visibility', () => {
108124
const input = 'pub(in crate::testing) fn public_function_in_my_mod() {';
109-
const doc = generateFunctionDoc(input);
125+
const doc = generateFunctionDoc(input, true, true, true);
110126
assert.ok(doc.includes('Describe this function'), 'Missing main description');
111127
});
112128

113129
it('handles pub(self) visibility', () => {
114130
const input = 'pub(self) fn public_function_in_nested() {';
115-
const doc = generateFunctionDoc(input);
131+
const doc = generateFunctionDoc(input, true, true, true);
116132
assert.ok(doc.includes('# Examples'), 'Missing example section');
117133
});
118134

119135
it('handles pub(super) visibility', () => {
120136
const input = 'pub(super) fn public_function_in_super_mod() {';
121-
const doc = generateFunctionDoc(input);
137+
const doc = generateFunctionDoc(input, true, true, true);
122138
assert.ok(doc.includes('Describe this function'), 'Missing placeholder description');
123139
});
140+
141+
it('respects includeExamples = false and hides examples section', () => {
142+
const input = 'fn private_internal() {}';
143+
const doc = generateFunctionDoc(input, false, false, true);
144+
assert.ok(!doc.includes('# Examples'), 'Should not include example section for private function');
145+
});
146+
147+
it('respects examplesOnlyForPublicOrExtern = true and hides examples for private function', () => {
148+
const input = 'fn private_internal() {}';
149+
const doc = generateFunctionDoc(input, true, true, true);
150+
assert.ok(!doc.includes('# Examples'), 'Should not include example section for private function');
151+
});
152+
153+
it('includes examples when examplesOnlyForPublicOrExtern = true and function is pub', () => {
154+
const input = 'pub fn exposed() {}';
155+
const doc = generateFunctionDoc(input, true, true, true);
156+
assert.ok(doc.includes('# Examples'), 'Should include example section for public function');
157+
});
124158
});
125159

126160
describe('generateStructDoc()', () => {
127161
it('returns null for unit struct', () => {
128-
assert.strictEqual(generateStructDoc('struct Empty;'), null);
129-
assert.strictEqual(generateStructDoc('struct Nothing {}'), null);
162+
assert.strictEqual(generateStructDoc('struct Empty;', true, true), null);
163+
assert.strictEqual(generateStructDoc('struct Nothing {}', true, true), null);
130164
});
131165

132166
it('documents tuple struct', () => {
133167
const input = 'struct Pair(i32, f64);';
134-
const doc = generateStructDoc(input);
168+
const doc = generateStructDoc(input, true, false);
135169
assert.ok(doc.includes('`field_0` (`i32`)'));
136170
assert.ok(doc.includes('`field_1` (`f64`)'));
137171
assert.ok(doc.includes('# Examples'));
@@ -146,7 +180,7 @@ describe('generateStructDoc()', () => {
146180
p: i32, q: i32, r: i32, s: i32, t: i32
147181
}
148182
`;
149-
const doc = generateStructDoc(input);
183+
const doc = generateStructDoc(input, true, true);
150184
assert.ok(doc.includes('# Fields'), 'Missing fields section');
151185
assert.ok((doc.match(/- `/g) || []).length >= 20, 'Should document 20+ fields');
152186
});
@@ -161,7 +195,7 @@ describe('generateEnumDoc()', () => {
161195
Write(String),
162196
}
163197
`;
164-
const doc = generateEnumDoc(input);
198+
const doc = generateEnumDoc(input, true, false);
165199
assert.ok(doc.includes('`Quit`'));
166200
assert.ok(doc.includes('`Move { x, y }`'));
167201
assert.ok(doc.includes('`Write(String)`'));
@@ -170,7 +204,7 @@ describe('generateEnumDoc()', () => {
170204

171205
it('returns null for invalid enum', () => {
172206
const badEnum = 'enum NotValid';
173-
assert.strictEqual(generateEnumDoc(badEnum), null);
207+
assert.strictEqual(generateEnumDoc(badEnum, true, true), null);
174208
});
175209

176210
it('handles enum with mixed variant types', () => {
@@ -182,7 +216,7 @@ describe('generateEnumDoc()', () => {
182216
ChangeColor(i32, i32, i32),
183217
}
184218
`;
185-
const doc = generateEnumDoc(input);
219+
const doc = generateEnumDoc(input, true, true);
186220
assert.ok(doc.includes('# Variants'), 'Missing variants section');
187221
assert.ok(doc.includes('- `Quit`'), 'Missing unit variant');
188222
assert.ok(doc.includes('- `Move { x, y }`'), 'Missing struct variant');
@@ -197,7 +231,7 @@ describe('generateEnumDoc()', () => {
197231
Field { a: i32, b: i32, c: i32, d: i32, e: i32 }
198232
}
199233
`;
200-
const doc = generateEnumDoc(input);
234+
const doc = generateEnumDoc(input, true, true);
201235
assert.ok(doc.includes('Tuple(u8, u16, u32, u64, usize)'), 'Missing tuple variant formatting');
202236
assert.ok(doc.includes('Field { a, b, c, d, e }'), 'Missing field variant formatting');
203237
});

0 commit comments

Comments
 (0)