You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cbmc/codedetect/scripts/generate_api_docs.py

1087 lines
32 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python3
"""
CodeDetect API文档生成工具
自动从源代码生成API文档支持:
- REST API端点文档
- WebSocket事件文档
- 内部模块API文档
- 配置参数文档
- 示例代码生成
"""
import ast
import os
import sys
import json
import re
import inspect
import importlib.util
from pathlib import Path
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass, asdict
from datetime import datetime
import yaml
import markdown
@dataclass
class APIEndpoint:
"""API端点信息"""
method: str
path: str
description: str
parameters: List[Dict[str, Any]]
responses: Dict[str, Dict[str, Any]]
examples: List[Dict[str, Any]]
authentication: bool
rate_limit: Optional[str] = None
@dataclass
class WebSocketEvent:
"""WebSocket事件信息"""
event: str
direction: str # 'client_to_server' or 'server_to_client'
description: str
payload: Dict[str, Any]
examples: List[Dict[str, Any]]
@dataclass
class ModuleAPI:
"""模块API信息"""
module_name: str
description: str
classes: List[Dict[str, Any]]
functions: List[Dict[str, Any]]
constants: List[Dict[str, Any]]
examples: List[str]
@dataclass
class ConfigParameter:
"""配置参数信息"""
name: str
type: str
default_value: Any
description: str
required: bool
options: Optional[List[str]] = None
class APIDocGenerator:
"""API文档生成器"""
def __init__(self, project_root: str, output_dir: str):
self.project_root = Path(project_root)
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
# 初始化数据结构
self.api_endpoints: List[APIEndpoint] = []
self.websocket_events: List[WebSocketEvent] = []
self.module_apis: List[ModuleAPI] = []
self.config_parameters: List[ConfigParameter] = []
# 忽略的文件和目录
self.ignore_patterns = [
'__pycache__',
'.git',
'.pytest_cache',
'venv',
'env',
'node_modules',
'build',
'dist',
'*.pyc'
]
def generate_all_docs(self):
"""生成所有API文档"""
print("🚀 开始生成API文档...")
# 扫描源代码
self._scan_source_code()
# 解析Flask路由
self._parse_flask_routes()
# 解析WebSocket事件
self._parse_websocket_events()
# 解析配置文件
self._parse_config_files()
# 生成各种文档
self._generate_rest_api_docs()
self._generate_websocket_docs()
self._generate_module_docs()
self._generate_config_docs()
self._generate_examples()
self._generate_index()
print("✅ API文档生成完成!")
def _scan_source_code(self):
"""扫描源代码文件"""
print("📂 扫描源代码...")
src_dir = self.project_root / "src"
if not src_dir.exists():
print(f"⚠️ 源代码目录不存在: {src_dir}")
return
for py_file in src_dir.rglob("*.py"):
if any(pattern in str(py_file) for pattern in self.ignore_patterns):
continue
try:
self._parse_python_file(py_file)
except Exception as e:
print(f"⚠️ 解析文件失败 {py_file}: {e}")
def _parse_python_file(self, file_path: Path):
"""解析Python文件"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
tree = ast.parse(content)
module_name = self._get_module_name(file_path)
module_api = ModuleAPI(
module_name=module_name,
description="",
classes=[],
functions=[],
constants=[],
examples=[]
)
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef):
self._parse_class(node, module_api)
elif isinstance(node, ast.FunctionDef):
self._parse_function(node, module_api)
elif isinstance(node, ast.Assign):
self._parse_assign(node, module_api)
if module_api.classes or module_api.functions:
self.module_apis.append(module_api)
except Exception as e:
print(f"⚠️ 解析Python文件失败 {file_path}: {e}")
def _parse_class(self, node: ast.ClassDef, module_api: ModuleAPI):
"""解析类定义"""
class_info = {
"name": node.name,
"docstring": ast.get_docstring(node) or "",
"methods": [],
"properties": []
}
for item in node.body:
if isinstance(item, ast.FunctionDef):
method_info = {
"name": item.name,
"docstring": ast.get_docstring(item) or "",
"parameters": self._get_function_parameters(item),
"returns": self._get_function_returns(item),
"decorators": [self._get_decorator_name(d) for d in item.decorator_list]
}
class_info["methods"].append(method_info)
module_api.classes.append(class_info)
def _parse_function(self, node: ast.FunctionDef, module_api: ModuleAPI):
"""解析函数定义"""
if not hasattr(node, 'parent_class'): # 不在类中的函数
function_info = {
"name": node.name,
"docstring": ast.get_docstring(node) or "",
"parameters": self._get_function_parameters(node),
"returns": self._get_function_returns(node),
"decorators": [self._get_decorator_name(d) for d in node.decorator_list]
}
module_api.functions.append(function_info)
def _parse_assign(self, node: ast.Assign, module_api: ModuleAPI):
"""解析赋值语句"""
for target in node.targets:
if isinstance(target, ast.Name):
if target.id.isupper(): # 常量
constant_info = {
"name": target.id,
"value": self._get_constant_value(node.value),
"docstring": "" # 可以从注释中提取
}
module_api.constants.append(constant_info)
def _get_module_name(self, file_path: Path) -> str:
"""获取模块名"""
relative_path = file_path.relative_to(self.project_root / "src")
module_path = str(relative_path.with_suffix('')).replace(os.sep, '.')
return module_path
def _get_function_parameters(self, node: ast.FunctionDef) -> List[Dict[str, Any]]:
"""获取函数参数"""
parameters = []
for arg in node.args.args:
param_info = {
"name": arg.arg,
"type": "",
"default": None,
"docstring": ""
}
# 尝试从类型注解获取类型
if arg.annotation:
param_info["type"] = self._get_type_string(arg.annotation)
parameters.append(param_info)
return parameters
def _get_function_returns(self, node: ast.FunctionDef) -> str:
"""获取函数返回类型"""
if node.returns:
return self._get_type_string(node.returns)
return ""
def _get_type_string(self, node: ast.AST) -> str:
"""获取类型字符串"""
if isinstance(node, ast.Name):
return node.id
elif isinstance(node, ast.Attribute):
return f"{node.value.id}.{node.attr}"
elif isinstance(node, ast.Subscript):
value = self._get_type_string(node.value)
slice_value = self._get_type_string(node.slice)
return f"{value}[{slice_value}]"
else:
return ""
def _get_decorator_name(self, node: ast.AST) -> str:
"""获取装饰器名称"""
if isinstance(node, ast.Name):
return node.id
elif isinstance(node, ast.Attribute):
return f"{node.value.id}.{node.attr}"
return ""
def _get_constant_value(self, node: ast.AST) -> Any:
"""获取常量值"""
if isinstance(node, ast.Constant):
return node.value
elif isinstance(node, ast.List):
return [self._get_constant_value(elt) for elt in node.elts]
elif isinstance(node, ast.Dict):
return {
self._get_constant_value(k): self._get_constant_value(v)
for k, v in zip(node.keys, node.values)
}
else:
return str(node)
def _parse_flask_routes(self):
"""解析Flask路由"""
print("🌐 解析Flask路由...")
api_files = [
self.project_root / "src" / "ui" / "api.py",
self.project_root / "src" / "api" / "routes.py"
]
for file_path in api_files:
if not file_path.exists():
continue
try:
self._parse_flask_file(file_path)
except Exception as e:
print(f"⚠️ 解析Flask文件失败 {file_path}: {e}")
def _parse_flask_file(self, file_path: Path):
"""解析Flask文件"""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 使用正则表达式提取路由信息
route_pattern = r'@(\w+)\.route\([\'"]([^\'\"]+)[\'"](?:,\s*methods=\[([^\]]+)\])?\)'
for match in re.finditer(route_pattern, content):
blueprint = match.group(1)
path = match.group(2)
methods = match.group(3)
if methods:
method_list = [m.strip().strip('\'"') for m in methods.split(',')]
else:
method_list = ['GET']
for method in method_list:
# 提取函数文档字符串
func_start = match.end()
func_pattern = r'def\s+(\w+)\s*\([^)]*\):\s*"""([^"]*)"""'
func_match = re.search(func_pattern, content[func_start:])
description = ""
if func_match:
description = func_match.group(2).strip()
endpoint = APIEndpoint(
method=method,
path=path,
description=description,
parameters=[],
responses={},
examples=[],
authentication=True
)
self.api_endpoints.append(endpoint)
def _parse_websocket_events(self):
"""解析WebSocket事件"""
print("🔌 解析WebSocket事件...")
# 从现有文档和代码中提取WebSocket事件
events = [
WebSocketEvent(
event="file_upload",
direction="client_to_server",
description="客户端上传文件",
payload={"file_id": "string", "filename": "string", "size": "number"},
examples=[{
"event": "file_upload",
"data": {"file_id": "file_123", "filename": "test.c", "size": 1024}
}]
),
WebSocketEvent(
event="verification_progress",
direction="server_to_client",
description="验证进度更新",
payload={"job_id": "string", "progress": "number", "status": "string"},
examples=[{
"event": "verification_progress",
"data": {"job_id": "job_456", "progress": 75, "status": "running"}
}]
),
WebSocketEvent(
event="verification_result",
direction="server_to_client",
description="验证结果通知",
payload={"job_id": "string", "result": "object", "success": "boolean"},
examples=[{
"event": "verification_result",
"data": {"job_id": "job_456", "result": {...}, "success": true}
}]
)
]
self.websocket_events.extend(events)
def _parse_config_files(self):
"""解析配置文件"""
print("⚙️ 解析配置文件...")
config_files = [
self.project_root / "config" / "default.yaml",
self.project_root / "config" / "development.yaml",
self.project_root / "config" / "production.yaml"
]
for config_file in config_files:
if not config_file.exists():
continue
try:
with open(config_file, 'r', encoding='utf-8') as f:
config_data = yaml.safe_load(f)
self._parse_config_data(config_data, config_file.name)
except Exception as e:
print(f"⚠️ 解析配置文件失败 {config_file}: {e}")
def _parse_config_data(self, config_data: Dict[str, Any], filename: str):
"""解析配置数据"""
def traverse_config(data: Dict[str, Any], prefix: str = ""):
for key, value in data.items():
full_key = f"{prefix}.{key}" if prefix else key
if isinstance(value, dict):
traverse_config(value, full_key)
else:
param = ConfigParameter(
name=full_key,
type=type(value).__name__,
default_value=value,
description=f"配置参数 {full_key} 来自 {filename}",
required=False
)
self.config_parameters.append(param)
if isinstance(config_data, dict):
traverse_config(config_data)
def _generate_rest_api_docs(self):
"""生成REST API文档"""
print("📄 生成REST API文档...")
md_content = """# REST API 文档
## 概述
CodeDetect提供RESTful API用于代码验证、规范生成和结果查询。
## 基础信息
- **基础URL**: `http://localhost:8080/api`
- **认证方式**: Bearer Token
- **内容类型**: `application/json`
- **字符编码**: UTF-8
## 通用响应格式
所有API响应都遵循以下格式
```json
{
"success": true,
"data": {},
"message": "操作成功",
"timestamp": "2024-01-01T00:00:00Z"
}
```
错误响应格式:
```json
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "错误描述",
"details": {}
},
"timestamp": "2024-01-01T00:00:00Z"
}
```
## API端点列表
"""
# 按方法分组
endpoints_by_method = {}
for endpoint in self.api_endpoints:
if endpoint.method not in endpoints_by_method:
endpoints_by_method[endpoint.method] = []
endpoints_by_method[endpoint.method].append(endpoint)
for method in ['GET', 'POST', 'PUT', 'DELETE']:
if method in endpoints_by_method:
md_content += f"### {method} 端点\n\n"
for endpoint in endpoints_by_method[method]:
md_content += f"#### {method} {endpoint.path}\n\n"
if endpoint.description:
md_content += f"**描述**: {endpoint.description}\n\n"
md_content += f"**认证**: {'' if endpoint.authentication else ''}\n\n"
if endpoint.parameters:
md_content += "**参数**:\n\n"
for param in endpoint.parameters:
md_content += f"- `{param['name']}` ({param['type']}): {param.get('description', '')}\n"
md_content += "\n"
if endpoint.examples:
md_content += "**示例**:\n\n"
for example in endpoint.examples:
md_content += "```json\n"
md_content += json.dumps(example, indent=2, ensure_ascii=False)
md_content += "\n```\n\n"
md_content += "---\n\n"
# 保存文档
with open(self.output_dir / "rest-api.md", 'w', encoding='utf-8') as f:
f.write(md_content)
def _generate_websocket_docs(self):
"""生成WebSocket文档"""
print("🔌 生成WebSocket文档...")
md_content = """# WebSocket API 文档
## 概述
CodeDetect使用WebSocket提供实时通信用于进度更新、结果通知等功能。
## 连接信息
- **WebSocket URL**: `ws://localhost:8080/ws`
- **协议**: WebSocket
- **消息格式**: JSON
## 消息格式
所有WebSocket消息都遵循以下格式
```json
{
"event": "事件名称",
"data": {},
"timestamp": "2024-01-01T00:00:00Z"
}
```
## 事件列表
"""
# 按方向分组
events_by_direction = {}
for event in self.websocket_events:
if event.direction not in events_by_direction:
events_by_direction[event.direction] = []
events_by_direction[event.direction].append(event)
for direction in ['client_to_server', 'server_to_client']:
direction_name = "客户端 → 服务器" if direction == 'client_to_server' else "服务器 → 客户端"
md_content += f"### {direction_name}\n\n"
if direction in events_by_direction:
for event in events_by_direction[direction]:
md_content += f"#### {event.event}\n\n"
md_content += f"**描述**: {event.description}\n\n"
if event.payload:
md_content += "**数据结构**:\n\n"
md_content += "```json\n"
md_content += json.dumps(event.payload, indent=2, ensure_ascii=False)
md_content += "\n```\n\n"
if event.examples:
md_content += "**示例**:\n\n"
for example in event.examples:
md_content += "```json\n"
md_content += json.dumps(example, indent=2, ensure_ascii=False)
md_content += "\n```\n\n"
md_content += "---\n\n"
# 保存文档
with open(self.output_dir / "websocket-api.md", 'w', encoding='utf-8') as f:
f.write(md_content)
def _generate_module_docs(self):
"""生成模块文档"""
print("📦 生成模块文档...")
md_content = """# 内部模块 API 文档
## 概述
本文档描述了CodeDetect内部模块的API供开发者和贡献者使用。
## 模块列表
"""
for module in self.module_apis:
md_content += f"### {module.module_name}\n\n"
if module.description:
md_content += f"**描述**: {module.description}\n\n"
if module.classes:
md_content += "#### 类\n\n"
for class_info in module.classes:
md_content += f"##### {class_info['name']}\n\n"
if class_info['docstring']:
md_content += f"**说明**: {class_info['docstring']}\n\n"
if class_info['methods']:
md_content += "**方法**:\n\n"
for method in class_info['methods']:
md_content += f"- `{method['name']}({', '.join(p['name'] for p in method['parameters'])})`\n"
if method['docstring']:
md_content += f" - {method['docstring']}\n"
md_content += "\n"
if module.functions:
md_content += "#### 函数\n\n"
for function in module.functions:
md_content += f"##### {function['name']}()\n\n"
if function['docstring']:
md_content += f"**说明**: {function['docstring']}\n\n"
if function['parameters']:
md_content += "**参数**:\n\n"
for param in function['parameters']:
md_content += f"- `{param['name']}`: {param['type']}\n"
md_content += "\n"
if function['returns']:
md_content += f"**返回值**: {function['returns']}\n\n"
md_content += "---\n\n"
# 保存文档
with open(self.output_dir / "internal-api.md", 'w', encoding='utf-8') as f:
f.write(md_content)
def _generate_config_docs(self):
"""生成配置文档"""
print("⚙️ 生成配置文档...")
md_content = """# 配置参数文档
## 概述
本文档描述了CodeDetect的所有配置参数及其说明。
## 配置文件位置
- 默认配置: `config/default.yaml`
- 开发环境: `config/development.yaml`
- 生产环境: `config/production.yaml`
## 配置参数列表
"""
# 按类型分组
params_by_type = {}
for param in self.config_parameters:
if param.type not in params_by_type:
params_by_type[param.type] = []
params_by_type[param.type].append(param)
for param_type in sorted(params_by_type.keys()):
md_content += f"### {param_type} 类型\n\n"
for param in params_by_type[param_type]:
md_content += f"#### {param.name}\n\n"
md_content += f"**默认值**: `{param.default_value}`\n\n"
md_content += f"**是否必需**: {'' if param.required else ''}\n\n"
md_content += f"**说明**: {param.description}\n\n"
if param.options:
md_content += "**可选值**:\n\n"
for option in param.options:
md_content += f"- `{option}`\n"
md_content += "\n"
md_content += "---\n\n"
# 保存文档
with open(self.output_dir / "configuration.md", 'w', encoding='utf-8') as f:
f.write(md_content)
def _generate_examples(self):
"""生成示例代码"""
print("💻 生成示例代码...")
# 创建示例目录
examples_dir = self.output_dir / "examples"
examples_dir.mkdir(exist_ok=True)
# 生成各种示例
examples = {
"basic_usage.py": """#!/usr/bin/env python3
"""
\"\"\"
CodeDetect基础使用示例
演示如何使用CodeDetect进行基本的代码验证
\"\"\"
import asyncio
import json
from pathlib import Path
# 导入CodeDetect模块
from src.verify.cbmc_runner import CBMCRunner
from src.mutate.engine import MutationEngine
from src.parse.code_parser import CodeParser
async def basic_verification_example():
\"\"\"基础验证示例\"\"\"
print("=== 基础验证示例 ===")
# 示例代码
code = \"\"\"
int add(int a, int b) {
return a + b;
}
\"\"\"
# 解析代码
parser = CodeParser()
with open("temp_example.c", "w") as f:
f.write(code)
try:
# 解析函数信息
parse_result = parser.parse_file("temp_example.c")
print(f"找到 {len(parse_result.functions)} 个函数")
for func in parse_result.functions:
print(f"- {func.name}: {func.return_type}")
print(f" 参数: {[p.name + ': ' + p.type for p in func.parameters]}")
# 生成验证规范
specification = \"\"\"
void add_test() {
int a = __CPROVER_nondet_int();
int b = __CPROVER_nondet_int();
// 约束输入范围
__CPROVER_assume(a >= -1000 && a <= 1000);
__CPROVER_assume(b >= -1000 && b <= 1000);
int result = add(a, b);
// 验证结果
__CPROVER_assert(result == a + b, "addition_correct");
}
\"\"\"
# 运行验证
runner = CBMCRunner()
result = await runner.run_verification(
function_metadata={"name": "add"},
source_file="temp_example.c",
specification=specification
)
print(f"验证结果: {result.status}")
print(f"执行时间: {result.execution_time}s")
finally:
# 清理临时文件
if Path("temp_example.c").exists():
Path("temp_example.c").unlink()
async def mutation_example():
\"\"\"突变生成示例\"\"\"
print("\\n=== 突变生成示例 ===")
# 基础规范
base_spec = \"\"\"
void add_test() {
int a = __CPROVER_nondet_int();
int b = __CPROVER_nondet_int();
int result = add(a, b);
__CPROVER_assert(result == a + b, "addition_correct");
}
\"\"\"
# 函数元数据
function_metadata = [{
"name": "add",
"return_type": "int",
"parameters": [
{"name": "a", "type": "int"},
{"name": "b", "type": "int"}
],
"complexity_score": 0.3
}]
# 生成突变
engine = MutationEngine()
mutations = engine.generate_mutations(
base_spec,
function_metadata,
max_mutations=3
)
print(f"生成了 {len(mutations)} 个突变:")
for i, mutation in enumerate(mutations):
print(f"\\n突变 {i+1}:")
print(f"类型: {mutation.mutation_type}")
print(f"置信度: {mutation.confidence:.2f}")
print(f"规范:\\n{mutation.specification}")
async def main():
\"\"\"主函数\"\"\"
try:
await basic_verification_example()
await mutation_example()
except Exception as e:
print(f"示例执行失败: {e}")
if __name__ == "__main__":
asyncio.run(main())
""",
"freertos_example.py": """#!/usr/bin/env python3
"""
\"\"\"
FreeRTOS验证示例
演示如何使用CodeDetect验证FreeRTOS代码。
\"\"\"
import asyncio
from pathlib import Path
from src.verify.cbmc_runner import CBMCRunner
from src.mutate.engine import MutationEngine
async def freertos_task_verification():
\"\"\"FreeRTOS任务验证示例\"\"\"
print("=== FreeRTOS任务验证示例 ===")
# FreeRTOS任务代码
freertos_code = \"\"\"
#include "FreeRTOS.h"
#include "task.h"
typedef struct {
int task_id;
int counter;
int max_count;
BaseType_t should_stop;
} TaskParameters_t;
void vCounterTask(void *pvParameters) {
TaskParameters_t *params = (TaskParameters_t *)pvParameters;
// 参数验证
configASSERT(params != NULL);
configASSERT(params->task_id > 0);
configASSERT(params->max_count > 0);
while (params->should_stop == pdFALSE) {
if (params->counter < params->max_count) {
params->counter++;
}
vTaskDelay(pdMS_TO_TICKS(100));
}
vTaskDelete(NULL);
}
\"\"\"
# 保存代码到文件
with open("freertos_task_example.c", "w") as f:
f.write(freertos_code)
try:
# FreeRTOS验证规范
specification = \"\"\"
#include "FreeRTOS.h"
#include "task.h"
typedef struct {
int task_id;
int counter;
int max_count;
BaseType_t should_stop;
} TaskParameters_t;
void test_task_creation() {
TaskParameters_t params;
TaskHandle_t task_handle;
// 初始化参数
params.task_id = 1;
params.counter = 0;
params.max_count = 10;
params.should_stop = pdFALSE;
// 测试任务创建
BaseType_t result = xTaskCreate(
vCounterTask,
"CounterTask",
configMINIMAL_STACK_SIZE,
&params,
1,
&task_handle
);
__CPROVER_assert(result == pdPASS, "task_creation_success");
__CPROVER_assert(task_handle != NULL, "task_handle_not_null");
}
void test_parameter_validation() {
TaskParameters_t *params = (TaskParameters_t *)__CPROVER_allocate(sizeof(TaskParameters_t));
// 测试NULL指针检查
vCounterTask(params);
// 测试有效参数
params->task_id = __CPROVER_nondet_int();
params->max_count = __CPROVER_nondet_int();
__CPROVER_assume(params->task_id > 0);
__CPROVER_assume(params->max_count > 0);
vCounterTask(params);
}
\"\"\"
# 运行验证
runner = CBMCRunner()
result = await runner.run_verification(
function_metadata={"name": "vCounterTask"},
source_file="freertos_task_example.c",
specification=specification
)
print(f"FreeRTOS验证结果: {result.status}")
print(f"执行时间: {result.execution_time}s")
finally:
# 清理临时文件
if Path("freertos_task_example.c").exists():
Path("freertos_task_example.c").unlink()
async def main():
\"\"\"主函数\"\"\"
try:
await freertos_task_verification()
except Exception as e:
print(f"FreeRTOS示例执行失败: {e}")
if __name__ == "__main__":
asyncio.run(main())
"""
}
for filename, content in examples.items():
with open(examples_dir / filename, 'w', encoding='utf-8') as f:
f.write(content)
def _generate_index(self):
"""生成索引文档"""
print("📑 生成索引文档...")
md_content = f"""# CodeDetect API 文档
> 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
## 概述
CodeDetect是一个基于LLM和CBMC的C代码形式化验证系统。本文档提供了完整的API参考包括REST API、WebSocket事件、内部模块API和配置参数。
## 文档结构
### 1. [REST API](rest-api.md)
- API端点列表
- 请求/响应格式
- 认证和权限
- 示例代码
### 2. [WebSocket API](websocket-api.md)
- 实时通信事件
- 消息格式
- 连接管理
- 示例代码
### 3. [内部模块 API](internal-api.md)
- 核心模块接口
- 类和函数说明
- 使用示例
- 扩展开发
### 4. [配置参数](configuration.md)
- 系统配置
- 环境变量
- 参数说明
- 最佳实践
### 5. [示例代码](examples/)
- 基础使用示例
- FreeRTOS验证示例
- 自定义扩展示例
## 快速开始
### 安装依赖
```bash
pip install -r requirements.txt
```
### 基础使用
```python
from src.verify.cbmc_runner import CBMCRunner
from src.mutate.engine import MutationEngine
# 创建验证器
runner = CBMCRunner()
engine = MutationEngine()
# 运行验证
result = await runner.run_verification(
function_metadata={"name": "test_function"},
source_file="test.c",
specification="void test() { }"
)
```
## 贡献指南
如果您发现文档问题或想要贡献,请:
1. 查看源代码中的注释和文档字符串
2. 运行文档生成脚本
3. 提交Pull Request
## 技术支持
- 📧 邮箱: support@codedetect.com
- 📖 文档: [在线文档](https://docs.codedetect.com)
- 🐛 问题报告: [GitHub Issues](https://github.com/codedetect/issues)
---
*本文档由自动生成工具创建*
"""
# 保存索引文档
with open(self.output_dir / "README.md", 'w', encoding='utf-8') as f:
f.write(md_content)
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description='CodeDetect API文档生成工具')
parser.add_argument('--project-root', type=str, default='.',
help='项目根目录 (默认: .)')
parser.add_argument('--output-dir', type=str, default='docs/api',
help='输出目录 (默认: docs/api)')
parser.add_argument('--verbose', action='store_true',
help='详细输出')
args = parser.parse_args()
# 生成文档
generator = APIDocGenerator(args.project_root, args.output_dir)
generator.generate_all_docs()
print(f"\n📚 文档已生成到: {args.output_dir}")
print("📖 开始阅读: docs/api/README.md")
if __name__ == "__main__":
main()