Skip to content

feat: implement rustdoc comment generation support#190

Open
rockaxorb13 wants to merge 1 commit intoaccordproject:mainfrom
rockaxorb13:main
Open

feat: implement rustdoc comment generation support#190
rockaxorb13 wants to merge 1 commit intoaccordproject:mainfrom
rockaxorb13:main

Conversation

@rockaxorb13
Copy link

Description

This PR brings the Rust generator closer to feature parity by adding support for documentation comments. It implements a writeDescription helper method that converts Concerto model descriptions into standard Rust documentation comments (///).

Changes

  • Added writeDescription helper method to RustVisitor class.
  • Updated visitClassDeclaration to generate documentation for Structs and Enums.
  • Updated visitField to generate documentation for Fields (including HashMap support).
  • Updated visitRelationshipDeclaration to generate documentation for Relationships.

Testing & Verification

I verified this logic locally using a debug script.

Note on Upstream Parser Behavior:
I discovered that the current version of @accordproject/concerto-cto (v3.25.0) used in this repository appears to strip comments during AST parsing. As a result, thing.getDescription() returns undefined by default when parsing a string.

To verify that my RustVisitor logic works correctly, I used a script that manually injects descriptions into the ClassDeclaration objects in memory after parsing. This confirmed that the generator correctly formats and outputs the RustDoc comments when the data is present in the model.

Verification Script (debug-rust.js)

const { ModelManager, ModelFile } = require('@accordproject/concerto-core');
const { Parser } = require('@accordproject/concerto-cto');
const { CodeGen } = require('./index');
const FileWriter = require('@accordproject/concerto-util').FileWriter;

const cto = `namespace com.test
asset Car identified by vin {
  o String vin
  o String color
}`;

// 1. Setup
const modelManager = new ModelManager();
const ast = Parser.parse(cto);
const modelFile = new ModelFile(modelManager, ast, 'test.cto');
modelManager.addModelFile(modelFile);

// 2. Manual Injection (Simulating a working parser)
const carDecl = modelFile.getType('com.test.Car');
if (carDecl) {
    carDecl.getDescription = () => "Documentation for Car Class";
    
    const colorField = carDecl.getProperty('color');
    if (colorField) {
        colorField.getDescription = () => "Documentation for Color Field";
    }
}

// 3. Run Visitor
const visitor = new CodeGen.RustVisitor();
const parameters = { fileWriter: new FileWriter('./output') };

modelManager.accept(visitor, parameters);

here is the debug script output which I got, after the modifications I made to rustvisitor.js:
Screenshot
Line 7 shows that the comment has been injected.

I am uploading the two files, debug-rust.js here:
debug-rust.js

Signed-off-by: Aadityavardhan Singh <singhrashmi018@gmail.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds RustDoc (///) documentation comment generation to the Rust CTO code generator by introducing a writeDescription helper and calling it from several visitor methods when emitting Rust structs and their members.

Changes:

  • Added writeDescription(thing, parameters, indent) to emit /// lines from getDescription().
  • Updated visitClassDeclaration to emit RustDoc comments for generated structs.
  • Updated visitField (including HashMap handling) and visitRelationshipDeclaration to emit RustDoc comments for fields/relationships.
Comments suppressed due to low confidence (1)

lib/codegen/fromcto/rust/rustvisitor.js:311

  • PR description mentions generating docs for structs and enums, but this change only calls writeDescription from visitClassDeclaration (structs). If enum docs are intended, visitEnumDeclaration (and possibly visitEnumValueDeclaration) should also call writeDescription; otherwise please update the PR description to match actual behavior.
        this.writeDescription(classDeclaration, parameters, 0);
        parameters.fileWriter.writeLine(
            0,
            '#[derive(Debug, Clone, Serialize, Deserialize)]'
        );

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1351 to +1352
// Write '/// ' followed by the trimmed line
parameters.fileWriter.writeLine(indent, `/// ${line.trim()}`);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimming every doc line with line.trim() removes leading whitespace that may be meaningful for Markdown formatting (e.g., indented code blocks/lists). Also, for empty lines this generates "/// " (trailing whitespace) in the output; consider preserving leading whitespace (trim end only) and emitting "///" for blank lines to avoid trailing spaces in generated Rust.

Suggested change
// Write '/// ' followed by the trimmed line
parameters.fileWriter.writeLine(indent, `/// ${line.trim()}`);
// Preserve leading whitespace (important for Markdown),
// but trim trailing whitespace. For blank lines, emit
// "///" without a trailing space.
const trimmedEnd = line.replace(/\s+$/, '');
if (trimmedEnd === '') {
parameters.fileWriter.writeLine(indent, '///');
} else {
parameters.fileWriter.writeLine(indent, `/// ${trimmedEnd}`);
}

Copilot uses AI. Check for mistakes.
const description = thing.getDescription();
// Split by newline to handle multi-line comments cleanly
const lines = description.split(/\r?\n/);
lines.forEach(line => {
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file consistently uses parentheses for single-arg arrow functions (e.g., .forEach((property) => ...)); for consistency, consider changing lines.forEach(line => { ... }) to lines.forEach((line) => { ... }).

Suggested change
lines.forEach(line => {
lines.forEach((line) => {

Copilot uses AI. Check for mistakes.
* @private
*/
visitClassDeclaration(classDeclaration, parameters) {
this.writeDescription(classDeclaration, parameters, 0);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior (emitting RustDoc comments for classes/fields/relationships) isn’t covered by the existing RustVisitor unit tests. Please add tests that stub getDescription() for ClassDeclaration/Field/RelationshipDeclaration and assert the expected /// lines are written (including multi-line descriptions).

Copilot uses AI. Check for mistakes.
Comment on lines +1346 to +1347
if (thing.getDescription && thing.getDescription()) {
const description = thing.getDescription();
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writeDescription calls thing.getDescription() multiple times (in the condition and again when assigning), which can be inefficient and can repeat side effects if getDescription is computed. Consider calling it once, validating it's a string (or coercing via String()), and reusing the value.

Suggested change
if (thing.getDescription && thing.getDescription()) {
const description = thing.getDescription();
const description = thing.getDescription && thing.getDescription();
if (typeof description === 'string' && description.length > 0) {

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants