Skip to main content

torsh_ffi/
api_docs.rs

1//! API Documentation Generator for ToRSh FFI
2//!
3//! This module provides tools to automatically generate comprehensive API documentation
4//! for the ToRSh FFI bindings across different programming languages.
5
6#![allow(dead_code)]
7
8use crate::binding_generator::{FunctionSignature, TargetLanguage};
9use crate::error::FfiResult;
10use std::collections::HashMap;
11use std::fmt::Write;
12
13/// Documentation format types
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum DocFormat {
16    Markdown,
17    Html,
18    RestructuredText,
19    ApiDoc,
20    Javadoc,
21    Sphinx,
22    GoDoc,
23    SwiftDoc,
24    RDoc,
25    JuliaDoc,
26}
27
28impl DocFormat {
29    pub fn file_extension(&self) -> &'static str {
30        match self {
31            DocFormat::Markdown => "md",
32            DocFormat::Html => "html",
33            DocFormat::RestructuredText => "rst",
34            DocFormat::ApiDoc => "txt",
35            DocFormat::Javadoc => "html",
36            DocFormat::Sphinx => "rst",
37            DocFormat::GoDoc => "md",
38            DocFormat::SwiftDoc => "md",
39            DocFormat::RDoc => "Rd",
40            DocFormat::JuliaDoc => "md",
41        }
42    }
43
44    pub fn for_language(lang: &TargetLanguage) -> Self {
45        match lang {
46            TargetLanguage::Java => DocFormat::Javadoc,
47            TargetLanguage::Python => DocFormat::Sphinx,
48            TargetLanguage::Go => DocFormat::GoDoc,
49            TargetLanguage::Swift => DocFormat::SwiftDoc,
50            TargetLanguage::R => DocFormat::RDoc,
51            TargetLanguage::Julia => DocFormat::JuliaDoc,
52            _ => DocFormat::Markdown,
53        }
54    }
55}
56
57/// Function category for organization
58#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub enum FunctionCategory {
60    TensorCreation,
61    TensorOperations,
62    TensorManipulation,
63    NeuralNetworks,
64    Optimization,
65    Utilities,
66    MemoryManagement,
67    ErrorHandling,
68    Performance,
69}
70
71impl FunctionCategory {
72    pub fn description(&self) -> &'static str {
73        match self {
74            FunctionCategory::TensorCreation => "Functions for creating new tensors",
75            FunctionCategory::TensorOperations => "Mathematical operations on tensors",
76            FunctionCategory::TensorManipulation => {
77                "Functions for reshaping, indexing, and manipulating tensors"
78            }
79            FunctionCategory::NeuralNetworks => "Neural network layers and modules",
80            FunctionCategory::Optimization => "Optimizers and training utilities",
81            FunctionCategory::Utilities => "Utility and helper functions",
82            FunctionCategory::MemoryManagement => "Memory allocation and cleanup functions",
83            FunctionCategory::ErrorHandling => "Error management and diagnostics",
84            FunctionCategory::Performance => "Performance optimization and profiling",
85        }
86    }
87
88    pub fn from_function_name(name: &str) -> Self {
89        if name.contains("tensor_zeros")
90            || name.contains("tensor_ones")
91            || name.contains("tensor_rand")
92            || name.contains("tensor_new")
93        {
94            FunctionCategory::TensorCreation
95        } else if name.contains("tensor_add")
96            || name.contains("tensor_mul")
97            || name.contains("tensor_matmul")
98            || name.contains("tensor_sub")
99        {
100            FunctionCategory::TensorOperations
101        } else if name.contains("tensor_reshape")
102            || name.contains("tensor_transpose")
103            || name.contains("tensor_view")
104        {
105            FunctionCategory::TensorManipulation
106        } else if name.contains("linear")
107            || name.contains("conv")
108            || name.contains("relu")
109            || name.contains("module")
110        {
111            FunctionCategory::NeuralNetworks
112        } else if name.contains("sgd") || name.contains("adam") || name.contains("optimizer") {
113            FunctionCategory::Optimization
114        } else if name.contains("free") || name.contains("cleanup") {
115            FunctionCategory::MemoryManagement
116        } else if name.contains("error") || name.contains("clear") {
117            FunctionCategory::ErrorHandling
118        } else if name.contains("batch") || name.contains("performance") || name.contains("stats") {
119            FunctionCategory::Performance
120        } else {
121            FunctionCategory::Utilities
122        }
123    }
124}
125
126/// API documentation entry
127#[derive(Debug, Clone)]
128pub struct ApiDocEntry {
129    pub function: FunctionSignature,
130    pub category: FunctionCategory,
131    pub examples: Vec<String>,
132    pub notes: Vec<String>,
133    pub see_also: Vec<String>,
134    pub since_version: Option<String>,
135}
136
137impl ApiDocEntry {
138    pub fn new(function: FunctionSignature) -> Self {
139        let category = FunctionCategory::from_function_name(&function.name);
140        Self {
141            function,
142            category,
143            examples: Vec::new(),
144            notes: Vec::new(),
145            see_also: Vec::new(),
146            since_version: None,
147        }
148    }
149
150    pub fn with_example(mut self, example: String) -> Self {
151        self.examples.push(example);
152        self
153    }
154
155    pub fn with_note(mut self, note: String) -> Self {
156        self.notes.push(note);
157        self
158    }
159
160    pub fn with_see_also(mut self, reference: String) -> Self {
161        self.see_also.push(reference);
162        self
163    }
164
165    pub fn with_version(mut self, version: String) -> Self {
166        self.since_version = Some(version);
167        self
168    }
169}
170
171/// API documentation generator
172pub struct ApiDocGenerator {
173    target_language: TargetLanguage,
174    format: DocFormat,
175    entries: Vec<ApiDocEntry>,
176    metadata: HashMap<String, String>,
177}
178
179impl ApiDocGenerator {
180    pub fn new(target_language: TargetLanguage) -> Self {
181        let format = DocFormat::for_language(&target_language);
182        Self {
183            target_language,
184            format,
185            entries: Vec::new(),
186            metadata: HashMap::new(),
187        }
188    }
189
190    pub fn with_format(mut self, format: DocFormat) -> Self {
191        self.format = format;
192        self
193    }
194
195    pub fn add_entry(&mut self, entry: ApiDocEntry) {
196        self.entries.push(entry);
197    }
198
199    pub fn add_metadata(&mut self, key: String, value: String) {
200        self.metadata.insert(key, value);
201    }
202
203    pub fn load_standard_functions(&mut self) {
204        // Core tensor functions with examples
205        let tensor_zeros = FunctionSignature {
206            name: "torsh_tensor_zeros".to_string(),
207            return_type: "*mut TorshTensor".to_string(),
208            parameters: vec![
209                ("shape".to_string(), "*const c_int".to_string()),
210                ("shape_len".to_string(), "c_int".to_string()),
211            ],
212            description: "Create a tensor filled with zeros".to_string(),
213            is_unsafe: true,
214        };
215
216        let entry = ApiDocEntry::new(tensor_zeros)
217            .with_example(self.generate_example_for_function("torsh_tensor_zeros"))
218            .with_note("The shape array must contain positive integers".to_string())
219            .with_see_also("torsh_tensor_ones".to_string())
220            .with_version("0.1.0".to_string());
221        self.add_entry(entry);
222
223        let tensor_add = FunctionSignature {
224            name: "torsh_tensor_add".to_string(),
225            return_type: "*mut TorshTensor".to_string(),
226            parameters: vec![
227                ("a".to_string(), "*mut TorshTensor".to_string()),
228                ("b".to_string(), "*mut TorshTensor".to_string()),
229            ],
230            description: "Add two tensors element-wise".to_string(),
231            is_unsafe: true,
232        };
233
234        let entry = ApiDocEntry::new(tensor_add)
235            .with_example(self.generate_example_for_function("torsh_tensor_add"))
236            .with_note("Both tensors must have compatible shapes for broadcasting".to_string())
237            .with_see_also("torsh_tensor_sub".to_string())
238            .with_see_also("torsh_tensor_mul".to_string())
239            .with_version("0.1.0".to_string());
240        self.add_entry(entry);
241
242        let linear_create = FunctionSignature {
243            name: "torsh_linear_create".to_string(),
244            return_type: "*mut TorshModule".to_string(),
245            parameters: vec![
246                ("in_features".to_string(), "c_int".to_string()),
247                ("out_features".to_string(), "c_int".to_string()),
248                ("bias".to_string(), "bool".to_string()),
249            ],
250            description: "Create a linear (fully connected) layer".to_string(),
251            is_unsafe: true,
252        };
253
254        let entry = ApiDocEntry::new(linear_create)
255            .with_example(self.generate_example_for_function("torsh_linear_create"))
256            .with_note("The layer weights are initialized randomly".to_string())
257            .with_see_also("torsh_linear_forward".to_string())
258            .with_version("0.1.0".to_string());
259        self.add_entry(entry);
260
261        // Add more standard functions...
262        self.add_optimizer_functions();
263        self.add_utility_functions();
264    }
265
266    fn add_optimizer_functions(&mut self) {
267        let sgd_create = FunctionSignature {
268            name: "torsh_sgd_create".to_string(),
269            return_type: "*mut TorshOptimizer".to_string(),
270            parameters: vec![("learning_rate".to_string(), "c_float".to_string())],
271            description: "Create a Stochastic Gradient Descent optimizer".to_string(),
272            is_unsafe: true,
273        };
274
275        let entry = ApiDocEntry::new(sgd_create)
276            .with_example(self.generate_example_for_function("torsh_sgd_create"))
277            .with_note(
278                "Learning rate should be positive and typically between 0.001 and 0.1".to_string(),
279            )
280            .with_see_also("torsh_adam_create".to_string())
281            .with_version("0.1.0".to_string());
282        self.add_entry(entry);
283    }
284
285    fn add_utility_functions(&mut self) {
286        let get_error = FunctionSignature {
287            name: "torsh_get_last_error".to_string(),
288            return_type: "c_int".to_string(),
289            parameters: vec![
290                ("buffer".to_string(), "*mut c_char".to_string()),
291                ("buffer_size".to_string(), "c_int".to_string()),
292            ],
293            description: "Get the last error message".to_string(),
294            is_unsafe: true,
295        };
296
297        let entry = ApiDocEntry::new(get_error)
298            .with_example(self.generate_example_for_function("torsh_get_last_error"))
299            .with_note("Buffer should be large enough to hold the error message".to_string())
300            .with_see_also("torsh_clear_last_error".to_string())
301            .with_version("0.1.0".to_string());
302        self.add_entry(entry);
303    }
304
305    fn generate_example_for_function(&self, function_name: &str) -> String {
306        match self.target_language {
307            TargetLanguage::Python => self.generate_python_example(function_name),
308            TargetLanguage::Java => self.generate_java_example(function_name),
309            TargetLanguage::Go => self.generate_go_example(function_name),
310            TargetLanguage::CSharp => self.generate_csharp_example(function_name),
311            TargetLanguage::Swift => self.generate_swift_example(function_name),
312            TargetLanguage::R => self.generate_r_example(function_name),
313            TargetLanguage::Julia => self.generate_julia_example(function_name),
314            _ => self.generate_c_example(function_name),
315        }
316    }
317
318    fn generate_python_example(&self, function_name: &str) -> String {
319        match function_name {
320            "torsh_tensor_zeros" => r#"```python
321import torsh_ffi as torsh
322
323# Create a 2x3 tensor filled with zeros
324shape = [2, 3]
325tensor = torsh.tensor_zeros(shape)
326print(f"Created tensor with shape: {tensor.shape()}")
327```"#
328                .to_string(),
329            "torsh_tensor_add" => r#"```python
330import torsh_ffi as torsh
331
332# Create two tensors and add them
333a = torsh.tensor_ones([2, 3])
334b = torsh.tensor_ones([2, 3])
335result = torsh.tensor_add(a, b)
336print("Added two tensors successfully")
337```"#
338                .to_string(),
339            "torsh_linear_create" => r#"```python
340import torsh_ffi as torsh
341
342# Create a linear layer with 10 input features and 5 output features
343layer = torsh.linear_create(in_features=10, out_features=5, bias=True)
344print("Created linear layer")
345```"#
346                .to_string(),
347            _ => "```python\n# Example not available\n```".to_string(),
348        }
349    }
350
351    fn generate_java_example(&self, function_name: &str) -> String {
352        match function_name {
353            "torsh_tensor_zeros" => r#"```java
354import com.torsh.ffi.TorshBindings;
355
356// Create a 2x3 tensor filled with zeros
357int[] shape = {2, 3};
358TensorHandle tensor = TorshBindings.tensorZeros(shape);
359System.out.println("Created tensor with zeros");
360```"#
361                .to_string(),
362            "torsh_tensor_add" => r#"```java
363import com.torsh.ffi.TorshBindings;
364
365// Create two tensors and add them
366int[] shape = {2, 3};
367TensorHandle a = TorshBindings.tensorOnes(shape);
368TensorHandle b = TorshBindings.tensorOnes(shape);
369TensorHandle result = TorshBindings.tensorAdd(a, b);
370System.out.println("Added two tensors successfully");
371```"#
372                .to_string(),
373            _ => "```java\n// Example not available\n```".to_string(),
374        }
375    }
376
377    fn generate_go_example(&self, function_name: &str) -> String {
378        match function_name {
379            "torsh_tensor_zeros" => r#"```go
380package main
381
382import (
383    "fmt"
384    "github.com/torsh/go-bindings/torsh"
385)
386
387func main() {
388    // Create a 2x3 tensor filled with zeros
389    shape := []int32{2, 3}
390    tensor := torsh.TensorZeros(shape)
391    fmt.Println("Created tensor with zeros")
392}
393```"#
394                .to_string(),
395            _ => "```go\n// Example not available\n```".to_string(),
396        }
397    }
398
399    fn generate_csharp_example(&self, function_name: &str) -> String {
400        match function_name {
401            "torsh_tensor_zeros" => r#"```csharp
402using TorshBindings;
403
404// Create a 2x3 tensor filled with zeros
405int[] shape = {2, 3};
406IntPtr tensor = TorshAPI.TensorZeros(shape, shape.Length);
407Console.WriteLine("Created tensor with zeros");
408```"#
409                .to_string(),
410            _ => "```csharp\n// Example not available\n```".to_string(),
411        }
412    }
413
414    fn generate_swift_example(&self, function_name: &str) -> String {
415        match function_name {
416            "torsh_tensor_zeros" => r#"```swift
417import TorshBindings
418
419// Create a 2x3 tensor filled with zeros
420let shape: [Int32] = [2, 3]
421let tensor = tensorZeros(shape: shape)
422print("Created tensor with zeros")
423```"#
424                .to_string(),
425            _ => "```swift\n// Example not available\n```".to_string(),
426        }
427    }
428
429    fn generate_r_example(&self, function_name: &str) -> String {
430        match function_name {
431            "torsh_tensor_zeros" => r#"```r
432library(torsh)
433
434# Create a 2x3 tensor filled with zeros
435shape <- c(2L, 3L)
436tensor <- r_tensor_zeros(shape)
437cat("Created tensor with zeros\n")
438```"#
439                .to_string(),
440            _ => "```r\n# Example not available\n```".to_string(),
441        }
442    }
443
444    fn generate_julia_example(&self, function_name: &str) -> String {
445        match function_name {
446            "torsh_tensor_zeros" => r#"```julia
447using TorshBindings
448
449# Create a 2x3 tensor filled with zeros
450shape = Int32[2, 3]
451tensor = jl_tensor_zeros(shape)
452println("Created tensor with zeros")
453```"#
454                .to_string(),
455            _ => "```julia\n# Example not available\n```".to_string(),
456        }
457    }
458
459    fn generate_c_example(&self, function_name: &str) -> String {
460        match function_name {
461            "torsh_tensor_zeros" => r#"```c
462#include "torsh_ffi.h"
463
464// Create a 2x3 tensor filled with zeros
465int shape[] = {2, 3};
466TorshTensor* tensor = torsh_tensor_zeros(shape, 2);
467printf("Created tensor with zeros\n");
468```"#
469                .to_string(),
470            _ => "```c\n// Example not available\n```".to_string(),
471        }
472    }
473
474    pub fn generate_documentation(&self) -> FfiResult<String> {
475        match self.format {
476            DocFormat::Markdown => self.generate_markdown(),
477            DocFormat::Html => self.generate_html(),
478            DocFormat::RestructuredText => self.generate_rst(),
479            DocFormat::Sphinx => self.generate_sphinx(),
480            DocFormat::Javadoc => self.generate_javadoc(),
481            _ => self.generate_markdown(), // Default to markdown
482        }
483    }
484
485    fn generate_markdown(&self) -> FfiResult<String> {
486        let mut output = String::new();
487
488        // Header
489        writeln!(
490            output,
491            "# ToRSh {} API Documentation",
492            format!("{:?}", self.target_language)
493        )?;
494        writeln!(output)?;
495
496        // Metadata
497        if let Some(version) = self.metadata.get("version") {
498            writeln!(output, "**Version:** {}", version)?;
499        }
500        if let Some(generated) = self.metadata.get("generated_at") {
501            writeln!(output, "**Generated:** {}", generated)?;
502        }
503        writeln!(output)?;
504
505        // Table of Contents
506        writeln!(output, "## Table of Contents")?;
507        writeln!(output)?;
508
509        let mut categories: HashMap<FunctionCategory, Vec<&ApiDocEntry>> = HashMap::new();
510        for entry in &self.entries {
511            categories
512                .entry(entry.category.clone())
513                .or_default()
514                .push(entry);
515        }
516
517        for (category, _) in &categories {
518            writeln!(
519                output,
520                "- [{}](#{:?})",
521                category.description(),
522                format!("{:?}", category).to_lowercase().replace(' ', "-")
523            )?;
524        }
525        writeln!(output)?;
526
527        // Function documentation by category
528        for (category, entries) in categories {
529            writeln!(output, "## {}", category.description())?;
530            writeln!(output)?;
531
532            for entry in entries {
533                self.write_function_markdown(&mut output, entry)?;
534            }
535        }
536
537        Ok(output)
538    }
539
540    fn write_function_markdown(&self, output: &mut String, entry: &ApiDocEntry) -> FfiResult<()> {
541        let func = &entry.function;
542
543        // Function signature
544        writeln!(output, "### `{}`", func.name)?;
545        writeln!(output)?;
546        writeln!(output, "{}", func.description)?;
547        writeln!(output)?;
548
549        // Parameters
550        if !func.parameters.is_empty() {
551            writeln!(output, "**Parameters:**")?;
552            writeln!(output)?;
553            for (name, param_type) in &func.parameters {
554                writeln!(
555                    output,
556                    "- `{}`: {} - Parameter description",
557                    name, param_type
558                )?;
559            }
560            writeln!(output)?;
561        }
562
563        // Return value
564        writeln!(output, "**Returns:** `{}`", func.return_type)?;
565        writeln!(output)?;
566
567        // Examples
568        if !entry.examples.is_empty() {
569            writeln!(output, "**Example:**")?;
570            writeln!(output)?;
571            for example in &entry.examples {
572                writeln!(output, "{}", example)?;
573                writeln!(output)?;
574            }
575        }
576
577        // Notes
578        if !entry.notes.is_empty() {
579            writeln!(output, "**Notes:**")?;
580            writeln!(output)?;
581            for note in &entry.notes {
582                writeln!(output, "- {}", note)?;
583            }
584            writeln!(output)?;
585        }
586
587        // See also
588        if !entry.see_also.is_empty() {
589            writeln!(output, "**See also:** {}", entry.see_also.join(", "))?;
590            writeln!(output)?;
591        }
592
593        // Version
594        if let Some(version) = &entry.since_version {
595            writeln!(output, "**Since version:** {}", version)?;
596            writeln!(output)?;
597        }
598
599        writeln!(output, "---")?;
600        writeln!(output)?;
601
602        Ok(())
603    }
604
605    fn generate_html(&self) -> FfiResult<String> {
606        let mut output = String::new();
607
608        writeln!(output, "<!DOCTYPE html>")?;
609        writeln!(output, "<html>")?;
610        writeln!(output, "<head>")?;
611        writeln!(
612            output,
613            "    <title>ToRSh {} API Documentation</title>",
614            format!("{:?}", self.target_language)
615        )?;
616        writeln!(output, "    <style>")?;
617        writeln!(
618            output,
619            "        body {{ font-family: Arial, sans-serif; margin: 40px; }}"
620        )?;
621        writeln!(
622            output,
623            "        .function {{ margin: 20px 0; padding: 15px; border: 1px solid #ddd; }}"
624        )?;
625        writeln!(
626            output,
627            "        .signature {{ font-family: monospace; background: #f5f5f5; padding: 10px; }}"
628        )?;
629        writeln!(
630            output,
631            "        .example {{ background: #f9f9f9; padding: 10px; margin: 10px 0; }}"
632        )?;
633        writeln!(output, "    </style>")?;
634        writeln!(output, "</head>")?;
635        writeln!(output, "<body>")?;
636
637        writeln!(
638            output,
639            "<h1>ToRSh {} API Documentation</h1>",
640            format!("{:?}", self.target_language)
641        )?;
642
643        // Group by category
644        let mut categories: HashMap<FunctionCategory, Vec<&ApiDocEntry>> = HashMap::new();
645        for entry in &self.entries {
646            categories
647                .entry(entry.category.clone())
648                .or_default()
649                .push(entry);
650        }
651
652        for (category, entries) in categories {
653            writeln!(output, "<h2>{}</h2>", category.description())?;
654
655            for entry in entries {
656                writeln!(output, "<div class=\"function\">")?;
657                writeln!(output, "<h3>{}</h3>", entry.function.name)?;
658                writeln!(output, "<p>{}</p>", entry.function.description)?;
659
660                if !entry.examples.is_empty() {
661                    writeln!(output, "<div class=\"example\">")?;
662                    writeln!(output, "<h4>Example:</h4>")?;
663                    for example in &entry.examples {
664                        writeln!(output, "<pre>{}</pre>", example)?;
665                    }
666                    writeln!(output, "</div>")?;
667                }
668
669                writeln!(output, "</div>")?;
670            }
671        }
672
673        writeln!(output, "</body>")?;
674        writeln!(output, "</html>")?;
675
676        Ok(output)
677    }
678
679    fn generate_rst(&self) -> FfiResult<String> {
680        let mut output = String::new();
681
682        writeln!(
683            output,
684            "ToRSh {} API Documentation",
685            format!("{:?}", self.target_language)
686        )?;
687        writeln!(output, "{}", "=".repeat(50))?;
688        writeln!(output)?;
689
690        // Group by category and generate RST
691        let mut categories: HashMap<FunctionCategory, Vec<&ApiDocEntry>> = HashMap::new();
692        for entry in &self.entries {
693            categories
694                .entry(entry.category.clone())
695                .or_default()
696                .push(entry);
697        }
698
699        for (category, entries) in categories {
700            writeln!(output, "{}", category.description())?;
701            writeln!(output, "{}", "-".repeat(category.description().len()))?;
702            writeln!(output)?;
703
704            for entry in entries {
705                writeln!(output, "{}", entry.function.name)?;
706                writeln!(output, "{}", "~".repeat(entry.function.name.len()))?;
707                writeln!(output)?;
708                writeln!(output, "{}", entry.function.description)?;
709                writeln!(output)?;
710
711                if !entry.examples.is_empty() {
712                    writeln!(output, ".. code-block::")?;
713                    writeln!(output)?;
714                    for example in &entry.examples {
715                        for line in example.lines() {
716                            writeln!(output, "   {}", line)?;
717                        }
718                    }
719                    writeln!(output)?;
720                }
721            }
722        }
723
724        Ok(output)
725    }
726
727    fn generate_sphinx(&self) -> FfiResult<String> {
728        // Similar to RST but with Sphinx-specific directives
729        self.generate_rst()
730    }
731
732    fn generate_javadoc(&self) -> FfiResult<String> {
733        let mut output = String::new();
734
735        writeln!(output, "/**")?;
736        writeln!(output, " * ToRSh Java API Documentation")?;
737        writeln!(
738            output,
739            " * Auto-generated documentation for ToRSh Java bindings"
740        )?;
741        writeln!(output, " */")?;
742
743        // Generate Javadoc-style documentation
744        for entry in &self.entries {
745            writeln!(output, "/**")?;
746            writeln!(output, " * {}", entry.function.description)?;
747            writeln!(output, " *")?;
748
749            for (name, _) in &entry.function.parameters {
750                writeln!(output, " * @param {} parameter description", name)?;
751            }
752
753            writeln!(output, " * @return {}", entry.function.return_type)?;
754
755            if let Some(version) = &entry.since_version {
756                writeln!(output, " * @since {}", version)?;
757            }
758
759            writeln!(output, " */")?;
760            writeln!(output)?;
761        }
762
763        Ok(output)
764    }
765}
766
767/// Generate API documentation for a specific language and format
768pub fn generate_api_docs(target_language: TargetLanguage, format: DocFormat) -> FfiResult<String> {
769    let mut generator = ApiDocGenerator::new(target_language).with_format(format);
770
771    // Add metadata
772    generator.add_metadata("version".to_string(), "0.1.0-alpha.2".to_string());
773    generator.add_metadata("generated_at".to_string(), chrono::Utc::now().to_rfc3339());
774
775    // Load standard functions
776    generator.load_standard_functions();
777
778    generator.generate_documentation()
779}
780
781/// Generate documentation for all supported languages
782pub fn generate_all_api_docs() -> FfiResult<HashMap<TargetLanguage, String>> {
783    let languages = vec![
784        TargetLanguage::Python,
785        TargetLanguage::Java,
786        TargetLanguage::Go,
787        TargetLanguage::CSharp,
788        TargetLanguage::Swift,
789        TargetLanguage::R,
790        TargetLanguage::Julia,
791    ];
792
793    let mut results = HashMap::new();
794
795    for lang in languages {
796        let docs = generate_api_docs(lang.clone(), DocFormat::for_language(&lang))?;
797        results.insert(lang, docs);
798    }
799
800    Ok(results)
801}
802
803#[cfg(test)]
804mod tests {
805    use super::*;
806
807    #[test]
808    fn test_doc_format_for_language() {
809        assert_eq!(
810            DocFormat::for_language(&TargetLanguage::Java),
811            DocFormat::Javadoc
812        );
813        assert_eq!(
814            DocFormat::for_language(&TargetLanguage::Python),
815            DocFormat::Sphinx
816        );
817        assert_eq!(
818            DocFormat::for_language(&TargetLanguage::Go),
819            DocFormat::GoDoc
820        );
821    }
822
823    #[test]
824    fn test_function_category_from_name() {
825        assert_eq!(
826            FunctionCategory::from_function_name("torsh_tensor_zeros"),
827            FunctionCategory::TensorCreation
828        );
829        assert_eq!(
830            FunctionCategory::from_function_name("torsh_tensor_add"),
831            FunctionCategory::TensorOperations
832        );
833        assert_eq!(
834            FunctionCategory::from_function_name("torsh_linear_create"),
835            FunctionCategory::NeuralNetworks
836        );
837        assert_eq!(
838            FunctionCategory::from_function_name("torsh_sgd_create"),
839            FunctionCategory::Optimization
840        );
841    }
842
843    #[test]
844    fn test_api_doc_entry_creation() {
845        let func = FunctionSignature {
846            name: "test_function".to_string(),
847            return_type: "void".to_string(),
848            parameters: vec![],
849            description: "Test function".to_string(),
850            is_unsafe: false,
851        };
852
853        let entry = ApiDocEntry::new(func)
854            .with_example("Example code".to_string())
855            .with_note("Important note".to_string())
856            .with_version("1.0.0".to_string());
857
858        assert_eq!(entry.examples.len(), 1);
859        assert_eq!(entry.notes.len(), 1);
860        assert_eq!(entry.since_version, Some("1.0.0".to_string()));
861    }
862
863    #[test]
864    fn test_doc_generator_creation() {
865        let generator = ApiDocGenerator::new(TargetLanguage::Python);
866        assert_eq!(generator.target_language, TargetLanguage::Python);
867        assert_eq!(generator.format, DocFormat::Sphinx);
868    }
869
870    #[test]
871    fn test_markdown_generation() {
872        let mut generator =
873            ApiDocGenerator::new(TargetLanguage::Python).with_format(DocFormat::Markdown);
874        generator.load_standard_functions();
875
876        let docs = generator.generate_documentation();
877        assert!(docs.is_ok());
878
879        let content = docs.unwrap();
880        assert!(content.contains("# ToRSh Python API Documentation"));
881        assert!(content.contains("## Table of Contents"));
882    }
883}