字段说明测试
All checks were successful
API接口参数变更检测 / api-param-check (push) Successful in 16s

This commit is contained in:
2026-06-05 15:20:01 +08:00
parent 1d05aec86c
commit dbcc1a3490
2 changed files with 59 additions and 10 deletions

View File

@@ -254,6 +254,42 @@ def _param_description(param: FormalParameter) -> Optional[str]:
return None
def _parse_javadoc_params(source_code: str) -> Dict[str, Dict[str, str]]:
"""
使用正则从 Java 源代码中提取方法上的 Javadoc @param 描述。
返回结构:
{ method_name: { param_name: description } }
"""
javadoc_map: Dict[str, Dict[str, str]] = {}
# 匹配 Javadoc 块 + 其后的方法声明
# 简单启发式Javadoc 后面第一个标识符 + ( 视为方法名
pattern = re.compile(
r'/\*\*(?P<javadoc>.*?)\*/\s*(?:public|private|protected|static|\s)*'
r'[\w<>\[\],\.\s]+\s+(?P<method>\w+)\s*\(',
re.DOTALL | re.MULTILINE
)
for match in pattern.finditer(source_code):
javadoc_block = match.group('javadoc')
method_name = match.group('method')
param_descs: Dict[str, str] = {}
# 提取 @param 行
param_pattern = re.compile(r'@param\s+(\w+)\s+([^\n@]+)', re.IGNORECASE)
for p_match in param_pattern.finditer(javadoc_block):
p_name = p_match.group(1)
p_desc = p_match.group(2).strip()
if p_desc:
param_descs[p_name] = p_desc
if param_descs:
javadoc_map[method_name] = param_descs
return javadoc_map
class ControllerAstParser:
"""
基于 javalang 的 Controller 解析器。
@@ -268,6 +304,7 @@ class ControllerAstParser:
self.repo_root = repo_root
self.source_dir = source_dir
self._dto_cache: Dict[str, List[ApiParameter]] = {}
self._javadoc_map: Dict[str, Dict[str, str]] = {} # method_name -> param_name -> description
def parse_file_content(self, source: str, repo_relative_path: str) -> List[ApiEndpoint]:
"""
@@ -284,6 +321,9 @@ class ControllerAstParser:
print(f"[警告] 解析失败 {repo_relative_path}: {exc}")
return endpoints
# 解析当前文件的 Javadoc @param用于参数描述回退
self._javadoc_map = _parse_javadoc_params(source)
for type_decl in tree.types or []:
if not isinstance(type_decl, ClassDeclaration):
continue
@@ -323,7 +363,7 @@ class ControllerAstParser:
method_path = _ann_string(ann, "value", "path")
params = []
for p in method.parameters or []:
params.extend(self._extract_param(p))
params.extend(self._extract_param(p, method_name=method.name))
return ApiEndpoint(
http_method=_http_method(ann_name, ann),
@@ -335,7 +375,7 @@ class ControllerAstParser:
)
return None
def _extract_param(self, param: FormalParameter) -> List[ApiParameter]:
def _extract_param(self, param: FormalParameter, method_name: Optional[str] = None) -> List[ApiParameter]:
"""提取方法参数,@RequestBody 展开 DTO 字段;忽略框架注入参数。"""
type_name = _type_to_str(param.type)
name = _param_name(param)
@@ -347,6 +387,11 @@ class ControllerAstParser:
return self._expand_dto(type_name, "body")
desc = _param_description(param)
# Javadoc @param 回退(如果注解中没有描述)
if not desc and method_name and method_name in self._javadoc_map:
desc = self._javadoc_map[method_name].get(name)
return [
ApiParameter(
name=name,