18.3 文件生成技能
文件生成技能概述
文件生成技能是 Claude Code Skills 中用於自動化生成各種型別文件的重要工具。它可以根據程式碼、註釋和配置自動生成高質量的文件,顯著減少手動編寫文件的工作量。
python
## 文档类型
### 1\. API 文档生成
#### 1.1 REST API 文档
python
# src/skills/api_documentation_generator.py
from typing import Dict, Any, List
from claude_code_sdk import Skill, SkillContext, SkillResult
import re
class APIDocumentationGeneratorSkill(Skill):
"""API 文档生成技能"""
def __init__(self):
super().__init__(
name="api-documentation-generator",
version="1.0.0",
description="Generate API documentation from code"
)
def get_parameters_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "Path to the API file"
},
"code": {
"type": "string",
"description": "API code to document"
},
"framework": {
"type": "string",
"enum": ["flask", "fastapi", "express", "django"],
"description": "Framework used"
},
"output_format": {
"type": "string",
"enum": ["markdown", "html", "openapi"],
"description": "Output format"
},
"include_examples": {
"type": "boolean",
"description": "Include usage examples",
"default": True
}
},
"required": ["framework"]
}
def execute(self, parameters: Dict[str, Any], context: SkillContext) -> SkillResult:
try:
framework = parameters["framework"]
output_format = parameters.get("output_format", "markdown")
include_examples = parameters.get("include_examples", True)
# 获取代码
if "file_path" in parameters:
code = context.read_file(parameters["file_path"])
file_path = parameters["file_path"]
elif "code" in parameters:
code = parameters["code"]
file_path = "<inline>"
else:
return SkillResult(
success=False,
error="Either file_path or code must be provided"
)
# 解析 API
endpoints = self.parse_api(code, framework)
# 生成文档
documentation = self.generate_documentation(
endpoints, framework, output_format, include_examples
)
return SkillResult(
success=True,
data={
"file_path": file_path,
"framework": framework,
"output_format": output_format,
"endpoints": endpoints,
"endpoint_count": len(endpoints),
"documentation": documentation
}
)
except Exception as e:
return SkillResult(
success=False,
error=str(e)
)
)
def parse_api(self, code: str, framework: str) -> List[Dict]: """解析 API 端点""" parsers = { "flask": self.parse_flask, "fastapi": self.parse_fastapi, "express": self.parse_express, "django": self.parse_django }
parser = parsers.get(framework) if not parser: raise ValueError(f"Unsupported framework: {framework}")
return parser(code)
def parse_flask(self, code: str) -> List[Dict]: """解析 Flask 路由""" endpoints = []
# 匹配路由装饰器
route_pattern = r'@app.route(['"](%5B%5E'%22%5D+)['"]\s*,\s*methods=[([^]]+)])'
for match in re.finditer(route_pattern, code): path = match.group(1) methods_str = match.group(2)
# 解析方法
methods = [m.strip().strip(''"') for m in methods_str.split(',')]
# 获取函数定义
func_start = match.end() func_pattern = r'def\s+(\w+)\s*([^)]*):' func_match = re.search(func_pattern, code[func_start:func_start + 100])
if func_match: func_name = func_match.group(1)
# 提取文档字符串
docstring = self.extract_docstring(code, func_start + func_match.end())
# 提取参数
params = self.extract_flask_params(code, func_start + func_match.end())
endpoints.append({ "path": path, "methods": methods, "function": func_name, "description": docstring, "parameters": params })return endpoints
python
def parse_fastapi(self, code: str) -> List[Dict]: """解析 FastAPI 路由""" endpoints = []
# 匹配路由装饰器
route_pattern = r'@(app.|router.)?(get|post|put|delete|patch)(['"](%5B%5E'%22%5D+)['"])'
for match in re.finditer(route_pattern, code): method = match.group(2).upper() path = match.group(3)
# 获取函数定义
func_start = match.end() func_pattern = r'async\s+def\s+(\w+)\s*(([^)]*)):' func_match = re.search(func_pattern, code[func_start:func_start + 200])
if func_match: func_name = func_match.group(1) params_str = func_match.group(2)
# 提取文档字符串
docstring = self.extract_docstring(code, func_start + func_match.end())
# 提取参数
params = self.extract_fastapi_params(params_str)
endpoints.append({ "path": path, "methods": [method], "function": func_name, "description": docstring, "parameters": params })return endpoints
python
def parse_express(self, code: str) -> List[Dict]: """解析 Express 路由""" endpoints = []
# 匹配路由定义
route_pattern = r'app.(get|post|put|delete|patch)(['"](%5B%5E'%22%5D+)['"]\s*,\s*(\w+)'
for match in re.finditer(route_pattern, code): method = match.group(1).upper() path = match.group(2) handler = match.group(3)
endpoints.append({ "path": path, "methods": [method], "function": handler, "description": "", "parameters": [] })return endpoints
python
def parse_django(self, code: str) -> List[Dict]: """解析 Django 路由""" endpoints = []
# 匹配 URL 模式
url_pattern = r'path(['"](%5B%5E'%22%5D+)['"]\s*,\s*(\w+).as_view()'
for match in re.finditer(url_pattern, code): path = match.group(1) view = match.group(2)
endpoints.append({ "path": path, "methods": ["GET", "POST", "PUT", "DELETE"], "function": view, "description": "", "parameters": [] })return endpoints
python
def extract_docstring(self, code: str, start_pos: int) -> str: """提取文档字符串"""
# 查找三引号字符串
docstring_pattern = r'"""([^"]*)"""' match = re.search(docstring_pattern, code[start_pos:start_pos + 500])
if match: return match.group(1).strip()return ""
python
def extract_flask_params(self, code: str, start_pos: int) -> List[Dict]: """提取 Flask 参数""" params = []
# 查找 request.json 或 request.form
json_pattern = r'request.json.get(['"](%5B%5E'%22%5D+)['"]' for match in re.finditer(json_pattern, code[start_pos:start_pos + 500]): params.append({ "name": match.group(1), "type": "object", "required": False, "description": "" })return params
python
def extract_fastapi_params(self, params_str: str) -> List[Dict]: """提取 FastAPI 参数""" params = []
# 解析函数参数
param_pattern = r'(\w+):\s*(\w+)' for match in re.finditer(param_pattern, params_str): param_name = match.group(1) param_type = match.group(2)
if param_name not in ["self", "request"]: params.append({ "name": param_name, "type": param_type, "required": False, "description": "" })return params
python
def generate_documentation(self, endpoints: List[Dict], framework: str, output_format: str, include_examples: bool) -> str: """生成文档""" generators = { "markdown": self.generate_markdown, "html": self.generate_html, "openapi": self.generate_openapi }
generator = generators.get(output_format) if not generator: raise ValueError(f"Unsupported output format: {output_format}")
return generator(endpoints, framework, include_examples)
def generate_markdown(self, endpoints: List[Dict], framework: str, include_examples: bool) -> str: """生成 Markdown 文档""" doc = f"# API Documentation\n\n" doc += f"Framework: {framework}\n\n" doc += f"## Endpoints\n\n"
for endpoint in endpoints: methods = ", ".join(endpoint["methods"]) doc += f"### {methods} {endpoint['path']}\n\n"
if endpoint["description"]: doc += f"{endpoint['description']}\n\n"
if endpoint["parameters"]: doc += "#### Parameters\n\n" doc += "| Name | Type | Required | Description |\n" doc += "|------|------|----------|-------------|\n"
for param in endpoint["parameters"]: required = "Yes" if param.get("required") else "No" doc += f"| {param['name']} | {param['type']} | {required} | {param.get('description', '')} |\n"
doc += "\n"
if include_examples: doc += "#### Example Request\n\n" doc += f"`bash\n" method = endpoint["methods"][0] if endpoint["methods"] else "GET" doc += f"curl -X {method} http://localhost:8000{endpoint['path']}\n" doc += f"`\n\n"return doc
python
def generate_html(self, endpoints: List[Dict], framework: str, include_examples: bool) -> str: """生成 HTML 文档""" html = f"""<!DOCTYPE html>
```python
html = """
<html>
<head>
<title>API Documentation</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
.endpoint {{ margin: 20px 0; padding: 15px; border: 1px solid #ddd; }}
.method {{ display: inline-block; padding: 5px 10px; color: white; margin-right: 10px; }}
.GET {{ background-color: #61affe; }}
.POST {{ background-color: #49cc90; }}
.PUT {{ background-color: #fca130; }}
.DELETE {{ background-color: #f93e3e; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
<h1>API Documentation</h1>
<p>Framework: {framework}</p>
<h2>Endpoints</h2>
"""
for endpoint in endpoints:
methods = ", ".join(endpoint["methods"])
html += f"""
<div class="endpoint">
<h3>
<span class="method {endpoint['methods'][0] if endpoint['methods'] else 'GET'}">{methods}</span>
{endpoint['path']}
</h3>
"""
if endpoint["description"]:
html += f" <p>{endpoint['description']}</p>\n"
if endpoint["parameters"]:
html += " <h4>Parameters</h4>\n"
html += " <table>\n"
html += " <tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr>\n"
for param in endpoint["parameters"]:
required = "Yes" if param.get("required") else "No"
html += f" <tr><td>{param['name']}</td><td>{param['type']}</td><td>{required}</td><td>{param.get('description', '')}</td></tr>\n"
html += " </table>\n"
html += " </div>\n"
html += """
</body>
</html>
"""
return html
```python
def generate_openapi(self, endpoints: List[Dict], framework: str, include_examples: bool) -> str: """生成 OpenAPI 规范""" openapi = { "openapi": "3.0.0", "info": { "title": "API Documentation", "version": "1.0.0" }, "paths": {} }
for endpoint in endpoints: path = endpoint["path"] openapi["paths"][path] = {}
for method in endpoint["methods"]: method_lower = method.lower() openapi["paths"][path][method_lower] = { "summary": endpoint["description"], "responses": { "200": { "description": "Success" } } }
if endpoint["parameters"]: openapi["paths"][path][method_lower]["parameters"] = [] for param in endpoint["parameters"]: openapi["paths"][path][method_lower]["parameters"].append({ "name": param["name"], "in": "query", "required": param.get("required", False), "schema": { "type": param["type"] } })
import json return json.dumps(openapi, indent=2)
### 2\. 代码文档生成
#### 2.1 函数和类文档
bash
python
# src/skills/code_documentation_generator.py
from typing import Dict, Any, List
from claude_code_sdk import Skill, SkillContext, SkillResult
import re
class CodeDocumentationGeneratorSkill(Skill):
"""代码文档生成技能"""
def __init__(self):
super().__init__(
name="code-documentation-generator",
version="1.0.0",
description="Generate code documentation"
)
def get_parameters_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "Path to the code file"
},
"code": {
"type": "string",
"description": "Code to document"
},
"language": {
"type": "string",
"enum": ["python", "javascript", "java", "go"],
"description": "Programming language"
},
"output_format": {
"type": "string",
"enum": ["markdown", "html"],
"description": "Output format"
},
"include_private": {
"type": "boolean",
"description": "Include private members",
"default": False
}
},
"required": ["language"]
}
def execute(self, parameters: Dict[str, Any], context: SkillContext) -> SkillResult:
try:
language = parameters["language"]
output_format = parameters.get("output_format", "markdown")
include_private = parameters.get("include_private", False)
# 获取代码
if "file_path" in parameters:
code = context.read_file(parameters["file_path"])
file_path = parameters["file_path"]
elif "code" in parameters:
code = parameters["code"]
file_path = "<inline>"
else:
return SkillResult(
success=False,
error="Either file_path or code must be provided"
)
# 解析代码
elements = self.parse_code(code, language, include_private)
# 生成文档
documentation = self.generate_documentation(
elements, language, output_format
)
return SkillResult(
success=True,
data={
"file_path": file_path,
"language": language,
"output_format": output_format,
"elements": elements,
"element_count": len(elements),
"documentation": documentation
}
)
except Exception as e:
return SkillResult(
success=False,
error=str(e)
)
def parse_code(self, code: str, language: str,
include_private: bool) -> List[Dict]:
"""解析代码元素"""
parsers = {
"python": self.parse_python,
"javascript": self.parse_javascript,
"java": self.parse_java,
"go": self.parse_go
}
parser = parsers.get(language)
if not parser:
raise ValueError(f"Unsupported language: {language}")
return parser(code, include_private)
def parse_python(self, code: str, include_private: bool) -> List[Dict]:
"""解析 Python 代码"""
elements = []
# 解析类
class_pattern = r'class\s+(\w+)\s*(?:\([^)]*\))?:'
for match in re.finditer(class_pattern, code):
class_name = match.group(1)
# 检查是否为私有类
if not include_private and class_name.startswith('_'):
continue
# 提取类文档字符串
docstring = self.extract_docstring(code, match.end())
# 解析方法
methods = self.parse_python_methods(code, match.end(), include_private)
elements.append({
"type": "class",
"name": class_name,
"description": docstring,
"methods": methods
})
# 解析函数
func_pattern = r'^def\s+(\w+)\s*\([^)]*\):'
for match in re.finditer(func_pattern, code, re.MULTILINE):
func_name = match.group(1)
# 检查是否为私有函数
if not include_private and func_name.startswith('_'):
continue
# 提取函数文档字符串
docstring = self.extract_docstring(code, match.end())
# 提取参数
params = self.extract_python_params(code, match.end())
elements.append({
"type": "function",
"name": func_name,
"description": docstring,
"parameters": params
})
return elements
def parse_python_methods(self, code: str, start_pos: int,
include_private: bool) -> List[Dict]:
"""解析 Python 方法"""
methods = []
# 在类定义范围内查找方法
class_end = self.find_class_end(code, start_pos)
class_code = code[start_pos:class_end]
func_pattern = r'def\s+(\w+)\s*\([^)]*\):'
for match in re.finditer(func_pattern, class_code):
method_name = match.group(1)
# 检查是否为私有方法
if not include_private and method_name.startswith('_'):
continue
# 提取方法文档字符串
docstring = self.extract_docstring(class_code, match.end())
# 提取参数
params = self.extract_python_params(class_code, match.end())
methods.append({
"name": method_name,
"description": docstring,
"parameters": params
})
return methods
def extract_python_params(self, code: str, start_pos: int) -> List[Dict]:
"""提取 Python 参数"""
params = []
# 查找函数定义中的参数
func_def = code[start_pos:start_pos + 200]
param_pattern = r'(\w+)\s*(?::\s*(\w+))?'
# 在括号内查找参数
match = re.search(r'\(([^)]*)\)', func_def)
if match:
params_str = match.group(1)
for param_match in re.finditer(param_pattern, params_str):
param_name = param_match.group(1)
param_type = param_match.group(2) or "Any"
if param_name not in ["self", "cls"]:
params.append({
"name": param_name,
"type": param_type,
"description": ""
})
return params
def find_class_end(self, code: str, start_pos: int) -> int:
"""查找类定义结束位置"""
lines = code[start_pos:].split('\n')
base_indent = len(lines[0]) - len(lines[0].lstrip())
for i, line in enumerate(lines[1:], 1):
if line.strip() and not line.strip().startswith('#'):
indent = len(line) - len(line.lstrip())
if indent <= base_indent:
return start_pos + sum(len(l) + 1 for l in lines[:i])
return len(code)
def parse_javascript(self, code: str, include_private: bool) -> List[Dict]:
"""解析 JavaScript 代码"""
elements = []
# 解析类
class_pattern = r'class\s+(\w+)\s*\{'
for match in re.finditer(class_pattern, code):
class_name = match.group(1)
# 检查是否为私有类
if not include_private and class_name.startswith('_'):
continue
# 提取类注释
comment = self.extract_js_comment(code, match.start())
# 解析方法
methods = self.parse_js_methods(code, match.end(), include_private)
elements.append({
"type": "class",
"name": class_name,
"description": comment,
"methods": methods
})
# 解析函数
func_pattern = r'function\s+(\w+)\s*\(|const\s+(\w+)\s*=\s*\([^)]*\)\s*=>'
for match in re.finditer(func_pattern, code):
func_name = match.group(1) or match.group(2)
# 检查是否为私有函数
if not include_private and func_name.startswith('_'):
continue
# 提取函数注释
comment = self.extract_js_comment(code, match.start())
elements.append({
"type": "function",
"name": func_name,
"description": comment,
"parameters": []
})
return elements
def parse_js_methods(self, code: str, start_pos: int,
include_private: bool) -> List[Dict]:
"""解析 JavaScript 方法"""
methods = []
# 在类定义范围内查找方法
class_end = self.find_js_class_end(code, start_pos)
class_code = code[start_pos:class_end]
method_pattern = r'(\w+)\s*\([^)]*\)\s*\{'
for match in re.finditer(method_pattern, class_code):
method_name = match.group(1)
# 检查是否为私有方法
if not include_private and method_name.startswith('_'):
continue
# 提取方法注释
comment = self.extract_js_comment(class_code, match.start())
methods.append({
"name": method_name,
"description": comment,
"parameters": []
})
return methods
def extract_js_comment(self, code: str, pos: int) -> str:
"""提取 JavaScript 注释"""
# 查找 JSDoc 注释
comment_pattern = r'/\*\*([^*]|\*[^/])*\*/'
match = re.search(comment_pattern, code[max(0, pos - 500):pos])
if match:
comment = match.group(0)
# 移除注释标记
comment = re.sub(r'/\*\*|\*/|\*\s?', '', comment)
return comment.strip()
return ""
def find_js_class_end(self, code: str, start_pos: int) -> int:
"""查找 JavaScript 类定义结束位置"""
brace_count = 1
i = start_pos
while i < len(code) and brace_count > 0:
if code[i] == '{':
brace_count += 1
elif code[i] == '}':
brace_count -= 1
i += 1
return i
def parse_java(self, code: str, include_private: bool) -> List[Dict]:
"""解析 Java 代码"""
# 简化实现
return []
def parse_go(self, code: str, include_private: bool) -> List[Dict]:
"""解析 Go 代码"""
# 简化实现
return []
def generate_documentation(self, elements: List[Dict], language: str,
output_format: str) -> str:
"""生成文档"""
if output_format == "markdown":
return self.generate_markdown(elements, language)
elif output_format == "html":
return self.generate_html(elements, language)
else:
raise ValueError(f"Unsupported output format: {output_format}")
def generate_markdown(self, elements: List[Dict], language: str) -> str:
"""生成 Markdown 文档"""
doc = f"# Code Documentation\n\n"
doc += f"Language: {language}\n\n"
for element in elements:
if element["type"] == "class":
doc += f"## Class: {element['name']}\n\n"
if element["description"]:
doc += f"{element['description']}\n\n"
if element["methods"]:
doc += "### Methods\n\n"
for method in element["methods"]:
doc += f"#### {method['name']}\n\n"
if method["description"]:
doc += f"{method['description']}\n\n"
if method["parameters"]:
doc += "**Parameters:**\n\n"
for param in method["parameters"]:
doc += f"- `{param['name']}` ({param['type']}): {param.get('description', '')}\n"
doc += "\n"
elif element["type"] == "function":
doc += f"## Function: {element['name']}\n\n"
if element["description"]:
doc += f"{element['description']}\n\n"
if element["parameters"]:
doc += "**Parameters:**\n\n"
for param in element["parameters"]:
doc += f"- `{param['name']}` ({param['type']}): {param.get('description', '')}\n"
doc += "\n"
return doc
def generate_html(self, elements: List[Dict], language: str) -> str:
"""生成 HTML 文档"""
html = f"""<!DOCTYPE html>
<html>
<head>
<title>Code Documentation</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
.class, .function {{ margin: 20px 0; padding: 15px; border: 1px solid #ddd; }}
.method {{ margin: 10px 0; padding: 10px; border-left: 3px solid #007bff; }}
code {{ background-color: #f4f4f4; padding: 2px 5px; }}
</style>
</head>
<body>
<h1>Code Documentation</h1>
<p>Language: {language}</p>
"""
for element in elements:
if element["type"] == "class":
html += f"""
<div class="class">
<h2>Class: {element['name']}</h2>
"""
if element["description"]:
html += f" <p>{element['description']}</p>\n"
if element["methods"]:
html += " <h3>Methods</h3>\n"
for method in element["methods"]:
html += f"""
<div class="method">
<h4>{method['name']}</h4>
"""
if method["description"]:
html += f" <p>{method['description']}</p>\n"
if method["parameters"]:
html += " <p><strong>Parameters:</strong></p>\n"
html += " <ul>\n"
for param in method["parameters"]:
html += f" <li><code>{param['name']}</code> ({param['type']}): {param.get('description', '')}</li>\n"
html += " </ul>\n"
html += " </div>\n"
html += " </div>\n"
elif element["type"] == "function":
html += f"""
<div class="function">
<h2>Function: {element['name']}</h2>
"""
if element["description"]:
html += f" <p>{element['description']}</p>\n"
if element["parameters"]:
html += " <p><strong>Parameters:</strong></p>\n"
html += " <ul>\n"
for param in element["parameters"]:
html += f" <li><code>{param['name']}</code> ({param['type']}): {param.get('description', '')}</li>\n"
html += " </ul>\n"
html += " </div>\n"
html += """
</body>
</html>
"""
return html
## 使用示例
### 1. 生成 API 文档
# examples/generate_api_docs.py
from skills.api_documentation_generator import APIDocumentationGeneratorSkill
from claude_code_sdk import SkillContext
skill = APIDocumentationGeneratorSkill()
context = SkillContext()
result = skill.execute(
{
"file_path": "src/api.py",
"framework": "flask",
"output_format": "markdown",
"include_examples": True
},
context
)
print(result.data["documentation"])
### 2\. 生成代码文档
bash
python
# examples/generate_code_docs.py
from skills.code_documentation_generator import CodeDocumentationGeneratorSkill
from claude_code_sdk import SkillContext
skill = CodeDocumentationGeneratorSkill()
context = SkillContext()
result = skill.execute(
{
"file_path": "src/utils.py",
"language": "python",
"output_format": "html",
"include_private": False
},
context
)
print(result.data["documentation"])
## 最佳实践
### 1. 文档编写规范
#### 1. 注释质量
- 使用清晰的语言
- 描述"为什么"而不是"是什么"
- 保持注释与代码同步
### 2. 文档结构
- 提供概述
- 包含示例
- 添加使用说明
### 3. 文档更新
- 及时更新文档
- 记录变更历史
- 维护版本信息
### 2\. 自动化文档生成
bash
markdown
#### 1. 集成到构建流程
- 在构建时生成文档
- 部署到文档服务器
- 自动更新文档
### 2. 持续集成
- 检查文档完整性
- 验证文档格式
- 生成文档报告
### 3. 文档审查
- 审查生成的文档
- 补充缺失信息
- 修正错误内容
## 总结文件生成技能可以顯著減少手動編寫文件的工作量,提高文件質量和一致性。透過自動化文件生成,開發者可以專注於程式碼編寫,同時確保文件的及時更新和準確性。
在下一節中,我們將探討測試生成技能。