From dbcc1a3490638e5d9114a9052023066c55ead9dc Mon Sep 17 00:00:00 2001 From: dongzi Date: Fri, 5 Jun 2026 15:20:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=AF=B4=E6=98=8E=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/checker/controller_ast_parser.py | 49 ++++++++++++++++++- .../controller/CultureClockInController.java | 20 +++++--- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/.gitea/checker/controller_ast_parser.py b/.gitea/checker/controller_ast_parser.py index 47d46f4..2f0e2e5 100644 --- a/.gitea/checker/controller_ast_parser.py +++ b/.gitea/checker/controller_ast_parser.py @@ -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.*?)\*/\s*(?:public|private|protected|static|\s)*' + r'[\w<>\[\],\.\s]+\s+(?P\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, diff --git a/ftb/src/main/java/ftb/test/controller/CultureClockInController.java b/ftb/src/main/java/ftb/test/controller/CultureClockInController.java index 5f53f89..8af14f9 100644 --- a/ftb/src/main/java/ftb/test/controller/CultureClockInController.java +++ b/ftb/src/main/java/ftb/test/controller/CultureClockInController.java @@ -42,8 +42,9 @@ public class CultureClockInController { /** * 打卡分享 - 获取随机图片 + * * @param lastCombo 上次组合 - * @param response HttpServletResponse + * @param response HttpServletResponse */ @PostMapping(value = "/random-preview1") public void getRandomPicPreview(@RequestParam(value = "lastCombo1", required = false) String lastCombo1, HttpServletRequest request, HttpServletResponse response) throws Exception { @@ -66,8 +67,9 @@ public class CultureClockInController { /** * 打卡分享 - 获取随机图片[base64] + * * @param lastCombo 上次组合 - * @param response HttpServletResponse + * @param response HttpServletResponse */ // @GetMapping(value = "/random-preview/base641") @PutMapping(value = "/random-preview/base64") @@ -89,8 +91,9 @@ public class CultureClockInController { /** * 打卡分享 - 获取随机图片[base64] + * * @param lastCombo 上次组合 - * @param response HttpServletResponse + * @param response HttpServletResponse */ @DeleteMapping(value = "/random-preview/delete") public ActionResult getRandomPicPreviewBase64(@RequestParam(value = "lastCombo", required = false) String lastCombo, HttpServletRequest request, HttpServletResponse response) throws Exception { @@ -112,6 +115,7 @@ public class CultureClockInController { /** * 打卡分享 - 打卡 + * * @param currentCombo 当前组合 * @return jnpf.base.ActionResult */ @@ -127,15 +131,14 @@ public class CultureClockInController { /** * 打卡动态 - 打卡记录列表 + * * @param cursorDate 游标日期(yyyy-MM-dd)[首次不传] - * @param limitNum 返回有数据的天数 + * @param limitNum 返回有数据的天数 * @return jnpf.base.ActionResult */ @GetMapping(value = "/dynamic1") -// public ActionResult getRecordList(@RequestParam(value = "cursorDate", required = false) String cursorDate, -// @RequestParam(value = "limitNum", required = false, defaultValue = "10") Integer limitNum) { - public ActionResult getRecordList(@ApiParam(value = "游标日期(yyyy-MM-dd),首次请求不传", required = false) @RequestParam(value = "cursorDate1", required = false) String cursorDate, - @ApiParam(value = "返回有数据的天数", required = false) @RequestParam(value = "limitNum", required = false, defaultValue = "10") Integer limitNum) { + public ActionResult getRecordList(@RequestParam(value = "cursorDate1", required = false) String cursorDate, + @RequestParam(value = "limitNum", required = false, defaultValue = "10") Integer limitNum) { limitNum = Math.max(10, Math.min(limitNum, 30)); RecordListVo recordList = cultureClockInService.getRecordList(cursorDate, limitNum); @@ -144,6 +147,7 @@ public class CultureClockInController { /** * 打卡日历 + * * @param year 年 * @return jnpf.base.ActionResult */