kcode-pi 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +35 -2
  2. package/dist/cli/kcode.d.ts +1 -0
  3. package/dist/cli/kcode.js +27 -4
  4. package/package.json +1 -1
  5. package/src/cli/kcode.ts +29 -4
  6. package/src/official/kingdee-skills.ts +60 -13
  7. package/src/rules/checker.ts +143 -0
  8. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/SKILL.md +2 -2
  9. package/vendor/kingdee-skills/ok-cosmic/SKILL.md +52 -101
  10. package/vendor/kingdee-skills/ok-cosmic/agents/openai.yaml +4 -4
  11. package/vendor/kingdee-skills/ok-cosmic/manifest.json +21 -20
  12. package/vendor/kingdee-skills/ok-cosmic/ok-cosmic-intro.html +1 -1
  13. package/vendor/kingdee-skills/ok-cosmic/rules/a-layer-rules.json +1 -1
  14. package/vendor/kingdee-skills/ok-cosmic/rules/anti-patterns.md +2 -2
  15. package/vendor/kingdee-skills/ok-cosmic/rules/coding-preferences.md +4 -4
  16. package/vendor/kingdee-skills/ok-cosmic/rules/constraints.md +3 -3
  17. package/vendor/kingdee-skills/ok-cosmic/rules/decision-matrix.md +8 -8
  18. package/vendor/kingdee-skills/ok-cosmic/rules/intent-routing.md +1 -1
  19. package/vendor/kingdee-skills/ok-cosmic/rules/post-check.md +19 -18
  20. package/vendor/kingdee-skills/ok-ksql/SKILL.md +9 -9
  21. package/vendor/kingdee-skills/ok-ksql/manifest.json +2 -1
  22. package/vendor/kingdee-skills/ok-ksql/references/ksql-datafix.md +2 -2
  23. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/pattern-matcher.py +0 -336
  24. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/review-score-calculator.py +0 -121
  25. package/vendor/kingdee-skills/ok-cosmic/CHANGELOG.md +0 -295
  26. package/vendor/kingdee-skills/ok-cosmic/README.md +0 -460
  27. package/vendor/kingdee-skills/ok-cosmic/requirements.txt +0 -2
  28. package/vendor/kingdee-skills/ok-cosmic/scripts/config_loader.py +0 -204
  29. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-api-knowledge.py +0 -910
  30. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-basedata-query.py +0 -359
  31. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-config-check.py +0 -181
  32. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-extpoints-query.py +0 -389
  33. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-form-metadata.py +0 -856
  34. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-check.py +0 -262
  35. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-lint.py +0 -293
  36. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/__init__.py +0 -2
  37. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/base.py +0 -393
  38. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/resource_check.py +0 -176
  39. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/scene_check.py +0 -375
  40. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/style_check.py +0 -434
  41. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/verify_check.py +0 -36
  42. package/vendor/kingdee-skills/ok-cosmic/scripts/route_client.py +0 -186
  43. package/vendor/kingdee-skills/ok-cosmic/scripts/script_utils.py +0 -40
  44. package/vendor/kingdee-skills/ok-cosmic/scripts/sqlite_cache.py +0 -142
  45. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-commons.jar +0 -0
  46. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-features.jar +0 -0
  47. package/vendor/kingdee-skills/ok-cosmic/setup/setup-mac.sh +0 -18
  48. package/vendor/kingdee-skills/ok-cosmic/setup/setup-windows.bat +0 -53
  49. package/vendor/kingdee-skills/ok-cosmic/setup/setup.jar +0 -0
  50. package/vendor/kingdee-skills/ok-ksql/scripts/ksql_lint.py +0 -363
@@ -1,262 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- cosmic-post-check.py — 苍穹代码生成后统一检查入口
5
-
6
- 逻辑:
7
- 1. 从目标文件/目录向上查找 Gradle 项目根目录(同时存在 build.gradle + settings.gradle)
8
- 2. 若找到 → 直接执行 Gradle 编译,编译通过后再执行代码规范检查
9
- 3. 若未找到 → 直接执行 cosmic-post-lint.py 代码规范检查
10
-
11
- 用法:
12
- python3 cosmic-post-check.py <file_or_directory> [--fix-hint] [--json] [--strict]
13
-
14
- 示例:
15
- python3 cosmic-post-check.py /path/to/project/code/module-bos/src/main/java/Foo.java
16
- python3 cosmic-post-check.py ./src/main/java/ --fix-hint
17
- """
18
-
19
- import os
20
- import re
21
- import subprocess
22
- import sys
23
- from pathlib import Path
24
- from typing import Dict, Optional
25
-
26
- from script_utils import run_cli
27
-
28
- SCRIPT_DIR = Path(__file__).resolve().parent
29
-
30
- # 全局 verbose 标志,通过 --verbose 开启
31
- VERBOSE = False
32
-
33
-
34
- def _verbose(msg: str):
35
- """在 --verbose 模式下输出诊断信息到 stderr。"""
36
- if VERBOSE:
37
- print(f" [verbose] {msg}", file=sys.stderr)
38
-
39
-
40
- # ══════════════════════════════════════════════
41
- # Gradle 项目检测
42
- # ══════════════════════════════════════════════
43
-
44
- def find_gradle_root(target: str) -> Optional[Path]:
45
- """从目标路径向上查找 Gradle 项目根目录。
46
-
47
- 判定条件:目录中同时存在 build.gradle(.kts) 和 settings.gradle(.kts)。
48
- """
49
- p = Path(target).resolve()
50
- if p.is_file():
51
- p = p.parent
52
- while p != p.parent:
53
- has_build = (p / "build.gradle").exists() or (p / "build.gradle.kts").exists()
54
- has_settings = (p / "settings.gradle").exists() or (p / "settings.gradle.kts").exists()
55
- if has_build and has_settings:
56
- return p
57
- p = p.parent
58
- return None
59
-
60
-
61
- def parse_modules(gradle_root: Path) -> Dict[str, Path]:
62
- """解析 settings.gradle 获取 模块名 → 目录 映射。
63
-
64
- 支持标准格式:
65
- include 'moduleName'
66
- project(':moduleName').projectDir = new File('relative/path')
67
- """
68
- modules: Dict[str, Path] = {}
69
- for name in ("settings.gradle", "settings.gradle.kts"):
70
- settings = gradle_root / name
71
- if settings.exists():
72
- break
73
- else:
74
- return modules
75
-
76
- text = settings.read_text(encoding="utf-8")
77
-
78
- # 收集所有 include 声明
79
- includes = re.findall(r"include\s+'([^']+)'", text)
80
-
81
- # 收集 projectDir 映射
82
- project_dirs: Dict[str, str] = dict(re.findall(
83
- r"project\(':([^']+)'\)\.projectDir\s*=\s*new\s+File\('([^']+)'\)",
84
- text,
85
- ))
86
-
87
- for mod_name in includes:
88
- if mod_name in project_dirs:
89
- modules[mod_name] = (gradle_root / project_dirs[mod_name]).resolve()
90
- else:
91
- modules[mod_name] = (gradle_root / mod_name).resolve()
92
-
93
- return modules
94
-
95
-
96
- def find_module(gradle_root: Path, target: str,
97
- modules: Dict[str, Path]) -> Optional[str]:
98
- """确定目标文件/目录属于哪个 Gradle 子模块。"""
99
- target_path = Path(target).resolve()
100
- # 优先匹配最长路径(最具体的模块)
101
- best_match: Optional[str] = None
102
- best_len = 0
103
- for name, mod_dir in modules.items():
104
- try:
105
- target_path.relative_to(mod_dir)
106
- if len(str(mod_dir)) > best_len:
107
- best_len = len(str(mod_dir))
108
- best_match = name
109
- except ValueError:
110
- continue
111
- return best_match
112
-
113
-
114
- # ══════════════════════════════════════════════
115
- # JAVA_HOME 解析(不做版本判断)
116
- # ══════════════════════════════════════════════
117
-
118
- def _read_properties(filepath: Path) -> Dict[str, str]:
119
- """读取 .properties 文件为 key→value 字典。"""
120
- props: Dict[str, str] = {}
121
- if not filepath.exists():
122
- return props
123
- for line in filepath.read_text(encoding="utf-8").splitlines():
124
- line = line.strip()
125
- if not line or line.startswith("#") or "=" not in line:
126
- continue
127
- k, v = line.split("=", 1)
128
- props[k.strip()] = v.strip()
129
- return props
130
-
131
-
132
- def resolve_java_home(gradle_root: Path) -> Optional[str]:
133
- """解析 JAVA_HOME 路径,不做版本判断。
134
-
135
- 优先级:gradle.properties 中 org.gradle.java.home → 环境变量 JAVA_HOME
136
- """
137
- props = _read_properties(gradle_root / "gradle.properties")
138
- explicit = props.get("org.gradle.java.home", "").strip()
139
- if explicit and os.path.isdir(explicit):
140
- return explicit
141
- env_home = os.environ.get("JAVA_HOME", "").strip()
142
- if env_home and os.path.isdir(env_home):
143
- return env_home
144
- return None
145
-
146
-
147
- # ══════════════════════════════════════════════
148
- # Gradle 编译
149
- # ══════════════════════════════════════════════
150
-
151
- def run_gradle(gradle_root: Path, module: Optional[str], java_home: Optional[str]) -> int:
152
- """执行 Gradle 编译,返回退出码。不预判 JDK 版本,直接尝试构建。"""
153
- # 定位 gradlew
154
- wrapper_name = "gradlew.bat" if sys.platform == "win32" else "gradlew"
155
- gradlew = gradle_root / wrapper_name
156
- if not gradlew.exists():
157
- print("[Warn] gradlew 不存在,尝试使用系统 gradle", file=sys.stderr)
158
- cmd_prefix = ["gradle"]
159
- else:
160
- # 确保 gradlew 有可执行权限
161
- if not os.access(gradlew, os.X_OK):
162
- os.chmod(gradlew, 0o755)
163
- cmd_prefix = [str(gradlew)]
164
-
165
- task = f":{module}:compileJava" if module else "compileJava"
166
- cmd = cmd_prefix + [task, "--console=plain"]
167
-
168
- env = os.environ.copy()
169
- if java_home:
170
- env["JAVA_HOME"] = java_home
171
-
172
- print("══════════════════════════════════════════════")
173
- print(" [Build] Gradle 编译检查")
174
- print("══════════════════════════════════════════════")
175
- print(f" [Project] 项目根目录: {gradle_root}")
176
- if module:
177
- print(f" [Module] 目标模块: {module}")
178
- print(f" [Java] JAVA_HOME: {java_home or '(未设置,由 Gradle 自行解析)'}")
179
- print(f" [Command] 编译命令: {' '.join(cmd)}")
180
- print("──────────────────────────────────────────────")
181
- print(flush=True)
182
-
183
- result = subprocess.run(cmd, cwd=str(gradle_root), env=env)
184
-
185
- print()
186
- print("══════════════════════════════════════════════")
187
- if result.returncode == 0:
188
- print(" ✔️ Gradle 编译成功,未发现编译错误。")
189
- else:
190
- print(f" ✖️ Gradle 编译失败 (exit code {result.returncode})")
191
- print(" 请根据上述编译错误信息修复代码。")
192
- print("══════════════════════════════════════════════")
193
-
194
- return result.returncode
195
-
196
-
197
- # ══════════════════════════════════════════════
198
- # Post-Lint 代码规范检查
199
- # ══════════════════════════════════════════════
200
-
201
- def run_post_lint(args: list) -> int:
202
- """执行 cosmic-post-lint.py 代码规范检查。"""
203
- post_lint = SCRIPT_DIR / "cosmic-post-lint.py"
204
- if not post_lint.exists():
205
- print(f"✖️ 未找到 {post_lint}", file=sys.stderr)
206
- return 1
207
-
208
- print("[Check] 执行代码规范检查")
209
- print(flush=True)
210
-
211
- cmd = [sys.executable, str(post_lint)] + args
212
- result = subprocess.run(cmd)
213
- return result.returncode
214
-
215
-
216
- # ══════════════════════════════════════════════
217
- # 主入口
218
- # ══════════════════════════════════════════════
219
-
220
- def main():
221
- global VERBOSE
222
-
223
- if len(sys.argv) < 2:
224
- print("用法: cosmic-post-check.py <file_or_directory> [--fix-hint] [--json] [--strict] [--verbose]")
225
- print()
226
- print("优先执行 Gradle 编译;编译通过后再执行代码规范检查。非 Gradle 项目直接执行规范检查。")
227
- sys.exit(1)
228
-
229
- # 解析 --verbose 并从 argv 中移除(不传给 post-lint)
230
- if "--verbose" in sys.argv:
231
- VERBOSE = True
232
- sys.argv.remove("--verbose")
233
-
234
- target = sys.argv[1]
235
- remaining_args = sys.argv[1:]
236
-
237
- # 1. 检测 Gradle 项目
238
- gradle_root = find_gradle_root(target)
239
- _verbose(f"Gradle 项目检测: {gradle_root or '未找到'}")
240
-
241
- if not gradle_root:
242
- # 非 Gradle → 直接执行代码规范检查
243
- sys.exit(run_post_lint(remaining_args))
244
-
245
- # 2. 解析 JAVA_HOME(不做版本判断)
246
- java_home = resolve_java_home(gradle_root)
247
- _verbose(f"JAVA_HOME: {java_home or '未设置'}")
248
-
249
- # 3. 直接执行 Gradle 编译
250
- modules = parse_modules(gradle_root)
251
- module = find_module(gradle_root, target, modules)
252
- exit_code = run_gradle(gradle_root, module, java_home)
253
- if exit_code != 0:
254
- sys.exit(exit_code)
255
-
256
- # 4. 编译成功 → 执行代码规范检查
257
- print("[Tip] Gradle 编译通过,继续执行代码规范检查...")
258
- sys.exit(run_post_lint(remaining_args))
259
-
260
-
261
- if __name__ == "__main__":
262
- sys.exit(run_cli(main))
@@ -1,293 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- cosmic-post-lint.py — 苍穹代码生成后自动校验脚本
5
-
6
- 依次调用 lint/ 子模块执行各类检查,汇总输出报告。
7
-
8
- 用法:
9
- python3 cosmic-post-lint.py <file_or_directory> [--fix-hint] [--json] [--strict]
10
-
11
- 示例:
12
- python3 cosmic-post-lint.py ./src/main/java/
13
- python3 cosmic-post-lint.py MyPlugin.java --fix-hint
14
- python3 cosmic-post-lint.py ./src/ --json --strict
15
- """
16
-
17
- import argparse
18
- import json
19
- import os
20
- import sys
21
- from concurrent.futures import ThreadPoolExecutor, as_completed
22
- from pathlib import Path
23
- from typing import List, Set
24
-
25
- from lint.base import Severity, LintIssue, LintReport
26
- from lint import scene_check, style_check, resource_check, verify_check
27
- from script_utils import FriendlyArgumentParser, run_cli
28
-
29
- SCRIPT_DIR = Path(__file__).resolve().parent
30
-
31
- # ──────────────────────────────────────────────
32
- # 检查器注册表
33
- # ──────────────────────────────────────────────
34
-
35
- # 每个检查器必须暴露 check(filepath, lines) -> List[LintIssue]
36
- # 新增检查器只需: 1) 在 lint/ 下新建 xxx_check.py 2) 在此列表注册
37
- CHECKERS = [
38
- {"name": "场景错配", "module": scene_check, "always": True},
39
- {"name": "编码偏好", "module": style_check, "always": True},
40
- {"name": "资源管理", "module": resource_check, "always": True},
41
- {"name": "验证注释", "module": verify_check, "always": False}, # 仅 --strict 模式
42
- ]
43
-
44
- # A 层硬约束:从 rules/a-layer-rules.json 加载(单一可信源),
45
- # 以保证 lint 行为与 rules/constraints.md、rules/post-check.md 的口径一致。
46
- def _load_a_layer_rule_ids() -> Set[str]:
47
- """从 rules/a-layer-rules.json 加载 A 层规则 ID 集合。"""
48
- json_path = SCRIPT_DIR.parent / "rules" / "a-layer-rules.json"
49
- try:
50
- data = json.loads(json_path.read_text(encoding="utf-8"))
51
- return set(data.get("a_layer_rule_ids", []))
52
- except (FileNotFoundError, json.JSONDecodeError, OSError) as e:
53
- print(f"[Warn] 无法加载 A 层规则配置 ({json_path}): {e}", file=sys.stderr)
54
- return set()
55
-
56
- A_LAYER_RULE_IDS = _load_a_layer_rule_ids()
57
-
58
-
59
- def get_rule_layer(rule_id: str) -> str:
60
- """根据规则 ID 推断当前问题属于 A/B/C 哪一层。"""
61
- if rule_id.startswith("VERIFY-"):
62
- return "C"
63
- if rule_id in A_LAYER_RULE_IDS:
64
- return "A"
65
- return "B"
66
-
67
-
68
- # ──────────────────────────────────────────────
69
- # 文件扫描
70
- # ──────────────────────────────────────────────
71
-
72
- def collect_java_files(path: str) -> List[str]:
73
- """递归收集所有 .java 文件"""
74
- p = Path(path)
75
- if p.is_file() and p.suffix == ".java":
76
- return [str(p)]
77
- elif p.is_dir():
78
- return sorted(str(f) for f in p.rglob("*.java"))
79
- else:
80
- return []
81
-
82
-
83
- def read_file_lines(filepath: str) -> List[str]:
84
- """读取文件内容,返回行列表"""
85
- try:
86
- with open(filepath, "r", encoding="utf-8") as f:
87
- return [l.rstrip("\n") for l in f.readlines()]
88
- except (UnicodeDecodeError, IOError):
89
- return []
90
-
91
-
92
- # ──────────────────────────────────────────────
93
- # 核心编排
94
- # ──────────────────────────────────────────────
95
-
96
- def check_file(filepath: str, strict: bool = False) -> List[LintIssue]:
97
- """对单个 Java 文件依次调用所有检查器"""
98
- lines = read_file_lines(filepath)
99
- if not lines:
100
- return []
101
-
102
- issues: List[LintIssue] = []
103
- for checker in CHECKERS:
104
- if not checker["always"] and not strict:
105
- continue
106
- try:
107
- issues.extend(checker["module"].check(filepath, lines))
108
- except Exception as e:
109
- issues.append(LintIssue(
110
- file=filepath,
111
- line=1,
112
- severity=Severity.ERROR,
113
- rule_id="LINT-EXCEPTION",
114
- message=f"{checker['name']} 检查执行失败: {e}",
115
- fix_hint="检查脚本实现或输入文件内容;必要时单独运行该校验脚本定位。",
116
- ))
117
-
118
- for issue in issues:
119
- if get_rule_layer(issue.rule_id) == "A" and issue.severity != Severity.ERROR:
120
- issue.severity = Severity.ERROR
121
-
122
- return issues
123
-
124
-
125
- # ──────────────────────────────────────────────
126
- # 报告输出
127
- # ──────────────────────────────────────────────
128
-
129
- RED = "\033[91m"
130
- YELLOW = "\033[93m"
131
- CYAN = "\033[96m"
132
- GREEN = "\033[92m"
133
- GRAY = "\033[90m"
134
- BOLD = "\033[1m"
135
- RESET = "\033[0m"
136
-
137
- SEVERITY_COLORS = {
138
- Severity.ERROR: RED,
139
- Severity.WARNING: YELLOW,
140
- Severity.INFO: CYAN,
141
- }
142
-
143
- SEVERITY_ICONS = {
144
- Severity.ERROR: "✖️",
145
- Severity.WARNING: "[WARN]",
146
- Severity.INFO: "[INFO]",
147
- }
148
-
149
-
150
- def print_report(report: LintReport, show_fix_hint: bool = False):
151
- """终端友好格式输出"""
152
- if not report.issues:
153
- print(f"\n{GREEN}{BOLD}✔️ 检查通过!共扫描 {report.total_files} 个文件,未发现问题。{RESET}\n")
154
- return
155
-
156
- by_file: dict[str, List[LintIssue]] = {}
157
- for issue in report.issues:
158
- by_file.setdefault(issue.file, []).append(issue)
159
-
160
- print(f"\n{BOLD}{'═' * 60}{RESET}")
161
- print(f"{BOLD} 苍穹代码校验报告{RESET}")
162
- print(f"{BOLD}{'═' * 60}{RESET}\n")
163
-
164
- for filepath, file_issues in by_file.items():
165
- rel = os.path.relpath(filepath)
166
- print(f" {BOLD}[File] {rel}{RESET}")
167
- for issue in sorted(file_issues, key=lambda x: x.line):
168
- color = SEVERITY_COLORS[issue.severity]
169
- icon = SEVERITY_ICONS[issue.severity]
170
- layer = get_rule_layer(issue.rule_id)
171
- print(f" {color}{icon} L{issue.line:>4d} [{layer}/{issue.rule_id}]{RESET} {issue.message}")
172
- if issue.source_line:
173
- print(f" {GRAY}> {issue.source_line}{RESET}")
174
- if show_fix_hint and issue.fix_hint:
175
- print(f" {GREEN}[Fix] {issue.fix_hint}{RESET}")
176
- print()
177
-
178
- print(f" {BOLD}{'─' * 50}{RESET}")
179
- print(f" [Stats] 扫描文件: {report.total_files} "
180
- f"总问题: {report.total_issues} "
181
- f"{RED}ERROR: {report.errors}{RESET} "
182
- f"{YELLOW}WARNING: {report.warnings}{RESET} "
183
- f"{CYAN}INFO: {report.infos}{RESET}")
184
-
185
- if report.errors > 0:
186
- print(f"\n {RED}{BOLD}[Error] 发现 {report.errors} 个错误,请修复后再提交。{RESET}\n")
187
- elif report.warnings > 0:
188
- print(f"\n {YELLOW}{BOLD}[Warn] 发现 {report.warnings} 个警告,建议修复。{RESET}\n")
189
- else:
190
- print(f"\n {GREEN}{BOLD}✔️ 仅有建议项,整体良好。{RESET}\n")
191
-
192
-
193
- def print_json_report(report: LintReport):
194
- """JSON 格式输出(适合 CI/CD 集成)"""
195
- output = {
196
- "summary": {
197
- "total_files": report.total_files,
198
- "total_issues": report.total_issues,
199
- "errors": report.errors,
200
- "warnings": report.warnings,
201
- "infos": report.infos,
202
- "passed": report.errors == 0,
203
- },
204
- "issues": [
205
- {
206
- "file": os.path.relpath(i.file),
207
- "line": i.line,
208
- "severity": i.severity.value,
209
- "layer": get_rule_layer(i.rule_id),
210
- "rule_id": i.rule_id,
211
- "message": i.message,
212
- "fix_hint": i.fix_hint,
213
- "source_line": i.source_line,
214
- }
215
- for i in report.issues
216
- ],
217
- }
218
- print(json.dumps(output, ensure_ascii=False, indent=2))
219
-
220
-
221
- # ──────────────────────────────────────────────
222
- # 入口
223
- # ──────────────────────────────────────────────
224
-
225
- def main():
226
- parser = FriendlyArgumentParser(
227
- description="苍穹代码生成后自动校验脚本",
228
- formatter_class=argparse.RawDescriptionHelpFormatter,
229
- epilog="""
230
- 检查模块:
231
- lint/scene_check.py 场景错配 (SCENE-*)
232
- lint/style_check.py 编码偏好 (STYLE-*)
233
- lint/resource_check.py 资源管理 (RESOURCE-*)
234
- lint/verify_check.py 验证注释治理 (VERIFY-*, C 层,仅 --strict)
235
-
236
- 扩展方式:
237
- 1. 在 lint/ 下新建 xxx_check.py,暴露 check(filepath, lines) 函数
238
- 2. 在 cosmic-post-lint.py 的 CHECKERS 列表中注册
239
- """,
240
- )
241
- parser.add_argument("path", help="要检查的 Java 文件或目录路径")
242
- parser.add_argument("--fix-hint", action="store_true", help="显示修复建议")
243
- parser.add_argument("--json", action="store_true", help="输出 JSON 格式(适合 CI)")
244
- parser.add_argument("--strict", action="store_true",
245
- help="严格模式:额外启用 C 层验证来源治理检查")
246
- parser.add_argument("--min-severity", choices=["error", "warning", "info"],
247
- default="info", help="最低报告级别 (默认: info)")
248
-
249
- args = parser.parse_args()
250
-
251
- severity_filter = {
252
- "error": {Severity.ERROR},
253
- "warning": {Severity.ERROR, Severity.WARNING},
254
- "info": {Severity.ERROR, Severity.WARNING, Severity.INFO},
255
- }[args.min_severity]
256
-
257
- files = collect_java_files(args.path)
258
- if not files:
259
- print(f"✖️ 未找到 Java 文件: {args.path}", file=sys.stderr)
260
- sys.exit(1)
261
-
262
- report = LintReport(total_files=len(files))
263
-
264
- def _check_one(fp):
265
- return fp, check_file(fp, strict=args.strict)
266
-
267
- if len(files) == 1:
268
- all_results = [_check_one(files[0])]
269
- else:
270
- all_results = [None] * len(files)
271
- with ThreadPoolExecutor(max_workers=min(len(files), 4)) as pool:
272
- future_to_idx = {
273
- pool.submit(_check_one, fp): i
274
- for i, fp in enumerate(files)
275
- }
276
- for future in as_completed(future_to_idx):
277
- all_results[future_to_idx[future]] = future.result()
278
-
279
- for _, issues in all_results:
280
- for issue in issues:
281
- if issue.severity in severity_filter:
282
- report.add(issue)
283
-
284
- if args.json:
285
- print_json_report(report)
286
- else:
287
- print_report(report, show_fix_hint=args.fix_hint)
288
-
289
- sys.exit(1 if report.errors > 0 else 0)
290
-
291
-
292
- if __name__ == "__main__":
293
- sys.exit(run_cli(main))
@@ -1,2 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """ok-cosmic post-lint 检查模块包。"""