import io, sys, os, re, json sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') ROOTS = [ r'e:\code\crm-backend-matt\crm-customer\src\main\java\com\crm\customer\domain', r'e:\code\crm-backend-matt\crm-rule\src\main\java', r'e:\code\crm-backend-matt\crm-preference\src\main\java', r'e:\code\crm-backend-matt\crm-base\src\main\java\com\crm\base\domain\result', ] WANT = { 'CustomerCreateDTO', 'CustomerUpdateDTO', 'CustomerQuickCreateDTO', 'CustomerSearchParam', 'CustomerPageParam', 'CustomerWorkspacePageParam', 'ContactDTO', 'ContactPageParam', 'MemberAddDTO', 'FollowCreateDTO', 'TransferInitiateDTO', 'TransferPageParam', 'ImportPageParam', 'OplogPageParam', 'FollowPageParam', 'CustomerReminderRule', 'SavedView', 'ColumnPreference', 'BaseParam', } def parse(path): name = os.path.splitext(os.path.basename(path))[0] if name not in WANT: return None t = open(path, encoding='utf-8').read() fields = [] # 字段行与其上方最近的 @Schema/@Comment lines = t.split('\n') for i, ln in enumerate(lines): m = re.match(r'\s*private\s+([\w.<>,\s]+?)\s+(\w+)\s*(=|;)', ln) if not m: continue typ, fname = m.group(1).strip(), m.group(2) desc = '' # 向上找 @Schema(description = "...") 或 @Comment('...') for j in range(i - 1, max(-1, i - 6), -1): up = lines[j] sm = re.search(r'@Schema\(description\s*=\s*"([^"]*)"', up) cm = re.search(r"@Comment\('([^']*)'\)", up) if sm or cm: desc = (sm or cm).group(1) break if re.match(r'\s*private\s+', up) or 'class ' in up: break fields.append({'f': fname, 't': typ, 'd': desc}) return {'name': name, 'fields': fields} out = {} for root in ROOTS: for dp, ds, fs in os.walk(root): for f in fs: if f.endswith('.java'): r = parse(os.path.join(dp, f)) if r and r['fields']: out.setdefault(r['name'], r['fields']) for k in sorted(out): print('==', k, '==') for x in out[k]: print(f" {x['f']} : {x['t']} -- {x['d']}")