kcode-pi 0.1.0

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 (219) hide show
  1. package/README.md +358 -0
  2. package/dist/cli/kcode.d.ts +15 -0
  3. package/dist/cli/kcode.js +153 -0
  4. package/dist/cli/main.d.ts +2 -0
  5. package/dist/cli/main.js +7 -0
  6. package/docs/KCODE_DISTRIBUTION.md +91 -0
  7. package/extensions/kingdee-harness.ts +180 -0
  8. package/extensions/kingdee-header.ts +122 -0
  9. package/extensions/kingdee-tools.ts +379 -0
  10. package/knowledge/.backup/v1.0.0/version.json +10 -0
  11. package/knowledge/cangqiong/product-notes.md +15 -0
  12. package/knowledge/common/business-flows.md +115 -0
  13. package/knowledge/common/config-guides.md +110 -0
  14. package/knowledge/common/error-patterns.md +170 -0
  15. package/knowledge/common/implementation.md +144 -0
  16. package/knowledge/cosmic/hard-constraints.md +38 -0
  17. package/knowledge/cosmic/ksql-datafix.md +34 -0
  18. package/knowledge/cosmic/platform-baseline.md +32 -0
  19. package/knowledge/cosmic/plugin-decision-matrix.md +40 -0
  20. package/knowledge/cosmic/review-checklist.md +40 -0
  21. package/knowledge/cosmic/unittest.md +35 -0
  22. package/knowledge/enterprise/api-reference.md +186 -0
  23. package/knowledge/enterprise/code-patterns.md +217 -0
  24. package/knowledge/enterprise/plugin-lifecycle.md +188 -0
  25. package/knowledge/enterprise/tables.json +159 -0
  26. package/knowledge/flagship/api-reference.md +237 -0
  27. package/knowledge/flagship/code-patterns.md +246 -0
  28. package/knowledge/flagship/cosmic-platform-note.md +15 -0
  29. package/knowledge/flagship/plugin-lifecycle.md +248 -0
  30. package/knowledge/flagship/tables.json +159 -0
  31. package/knowledge/version.json +10 -0
  32. package/knowledge/xinghan/product-notes.md +15 -0
  33. package/package.json +71 -0
  34. package/prompts/kd-discuss.md +11 -0
  35. package/prompts/kd-execute.md +12 -0
  36. package/prompts/kd-plan.md +12 -0
  37. package/prompts/kd-ship.md +12 -0
  38. package/prompts/kd-spec.md +12 -0
  39. package/prompts/kd-verify.md +12 -0
  40. package/skills/kd-check/SKILL.md +26 -0
  41. package/skills/kd-cosmic-dev/SKILL.md +82 -0
  42. package/skills/kd-cosmic-review/SKILL.md +90 -0
  43. package/skills/kd-cosmic-unittest/SKILL.md +92 -0
  44. package/skills/kd-debug/SKILL.md +30 -0
  45. package/skills/kd-discuss/SKILL.md +24 -0
  46. package/skills/kd-execute/SKILL.md +22 -0
  47. package/skills/kd-gen/SKILL.md +34 -0
  48. package/skills/kd-ksql/SKILL.md +86 -0
  49. package/skills/kd-plan/SKILL.md +24 -0
  50. package/skills/kd-ship/SKILL.md +22 -0
  51. package/skills/kd-spec/SKILL.md +24 -0
  52. package/skills/kd-verify/SKILL.md +22 -0
  53. package/themes/kcode-dark.json +81 -0
  54. package/vendor/kingdee-skills/cosmic-unittest/SKILL.md +788 -0
  55. package/vendor/kingdee-skills/cosmic-unittest/author-cache.json +5 -0
  56. package/vendor/kingdee-skills/cosmic-unittest/cosmic-unittest-skill-overview.html +746 -0
  57. package/vendor/kingdee-skills/cosmic-unittest/examples/business-test.md +205 -0
  58. package/vendor/kingdee-skills/cosmic-unittest/examples/common-test.md +257 -0
  59. package/vendor/kingdee-skills/cosmic-unittest/examples/formplugin-test.md +560 -0
  60. package/vendor/kingdee-skills/cosmic-unittest/examples/op-plugin-test.md +231 -0
  61. package/vendor/kingdee-skills/cosmic-unittest/examples/validator-test.md +232 -0
  62. package/vendor/kingdee-skills/cosmic-unittest/patterns/business-helper.md +184 -0
  63. package/vendor/kingdee-skills/cosmic-unittest/patterns/common-module.md +355 -0
  64. package/vendor/kingdee-skills/cosmic-unittest/patterns/convert-plugin.md +130 -0
  65. package/vendor/kingdee-skills/cosmic-unittest/patterns/formplugin.md +235 -0
  66. package/vendor/kingdee-skills/cosmic-unittest/patterns/op-plugin.md +226 -0
  67. package/vendor/kingdee-skills/cosmic-unittest/patterns/validator.md +206 -0
  68. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/SKILL.md +674 -0
  69. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/advanced-scenario-checklist.md +307 -0
  70. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/algox-performance-checklist.md +129 -0
  71. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/coding-standard-checklist.md +491 -0
  72. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/cosmic-api-checklist.md +285 -0
  73. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-access-checklist.md +261 -0
  74. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-transaction-checklist.md +390 -0
  75. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/domain-logic-checklist.md +295 -0
  76. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/form-plugin-checklist.md +508 -0
  77. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/infra-checklist.md +254 -0
  78. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ksql-checklist.md +305 -0
  79. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/lifecycle-checklist.md +298 -0
  80. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/operation-plugin-checklist.md +442 -0
  81. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/test-mock-checklist.md +120 -0
  82. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ui-performance-checklist.md +320 -0
  83. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/pattern-matcher.py +336 -0
  84. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/review-score-calculator.py +121 -0
  85. package/vendor/kingdee-skills/ok-cosmic/CHANGELOG.md +295 -0
  86. package/vendor/kingdee-skills/ok-cosmic/README.md +460 -0
  87. package/vendor/kingdee-skills/ok-cosmic/SKILL.md +287 -0
  88. package/vendor/kingdee-skills/ok-cosmic/agents/openai.yaml +17 -0
  89. package/vendor/kingdee-skills/ok-cosmic/assets/BatchImportPluginTemplate.java +93 -0
  90. package/vendor/kingdee-skills/ok-cosmic/assets/BillPlugInTemplate.java +156 -0
  91. package/vendor/kingdee-skills/ok-cosmic/assets/ConvertPlugInTemplate.java +255 -0
  92. package/vendor/kingdee-skills/ok-cosmic/assets/FormPluginTemplate.java +597 -0
  93. package/vendor/kingdee-skills/ok-cosmic/assets/IWorkflowPluginTemplate.java +91 -0
  94. package/vendor/kingdee-skills/ok-cosmic/assets/ListPluginTemplate.java +194 -0
  95. package/vendor/kingdee-skills/ok-cosmic/assets/OpPluginTemplate.java +201 -0
  96. package/vendor/kingdee-skills/ok-cosmic/assets/OpenApiControllerTemplate.java +103 -0
  97. package/vendor/kingdee-skills/ok-cosmic/assets/PrintPluginTemplate.java +95 -0
  98. package/vendor/kingdee-skills/ok-cosmic/assets/ReportFormPluginTemplate.java +257 -0
  99. package/vendor/kingdee-skills/ok-cosmic/assets/ReportListDataPluginTemplate.java +70 -0
  100. package/vendor/kingdee-skills/ok-cosmic/assets/StandardTreeListPluginTemplate.java +130 -0
  101. package/vendor/kingdee-skills/ok-cosmic/assets/TaskTemplate.java +80 -0
  102. package/vendor/kingdee-skills/ok-cosmic/assets/TreeListPluginTemplate.java +152 -0
  103. package/vendor/kingdee-skills/ok-cosmic/assets/WriteBackPlugInTemplate.java +286 -0
  104. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/attachment/AttachmentUploadBindSample.java +93 -0
  105. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/BotpTracePushSample.java +168 -0
  106. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/SampleConvertPlugin.java +223 -0
  107. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/cache/SampleCacheUsage.java +218 -0
  108. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/concurrent/SampleThreadPoolBatch.java +156 -0
  109. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectCrudSample.java +205 -0
  110. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectOpsSample.java +100 -0
  111. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/BeforeOperationConfirmSample.java +217 -0
  112. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ConfirmDialogSample.java +131 -0
  113. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/EntryRowCalculateSample.java +116 -0
  114. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/F7FilterSample.java +134 -0
  115. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/GetAndSetValueSample.java +176 -0
  116. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/HyperlinkJumpSample.java +124 -0
  117. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/OpenBillModalSample.java +253 -0
  118. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ReturnParentDataSample.java +295 -0
  119. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/TreeControlSample.java +140 -0
  120. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ViewControlOpsSample.java +132 -0
  121. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPluginBasicSample.java +170 -0
  122. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPreOpenFilterSample.java +68 -0
  123. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/message/MessageNotifySample.java +95 -0
  124. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/SampleMQConsumer.java +198 -0
  125. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/sample_mq.xml +15 -0
  126. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OpAddValidatorsSample.java +137 -0
  127. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OperationOptionBridgeSample.java +228 -0
  128. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/package-info.java +19 -0
  129. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BaseDataQuerySample.java +194 -0
  130. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BatchQuerySample.java +368 -0
  131. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/DataSetQueryStatSample.java +131 -0
  132. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportFormPlugin.java +179 -0
  133. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportListDataPlugin.java +616 -0
  134. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/snippets-guide.md +64 -0
  135. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/task/ScheduleTaskSample.java +160 -0
  136. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/workflow/SampleWorkflowPlugin.java +302 -0
  137. package/vendor/kingdee-skills/ok-cosmic/manifest.json +78 -0
  138. package/vendor/kingdee-skills/ok-cosmic/ok-cosmic-intro.html +903 -0
  139. package/vendor/kingdee-skills/ok-cosmic/references/adv/attachment-api.md +114 -0
  140. package/vendor/kingdee-skills/ok-cosmic/references/adv/botp-convert.md +98 -0
  141. package/vendor/kingdee-skills/ok-cosmic/references/adv/dynamic-object.md +113 -0
  142. package/vendor/kingdee-skills/ok-cosmic/references/adv/entity-metadata.md +123 -0
  143. package/vendor/kingdee-skills/ok-cosmic/references/adv/event-lifecycle.md +184 -0
  144. package/vendor/kingdee-skills/ok-cosmic/references/adv/flex-prop.md +114 -0
  145. package/vendor/kingdee-skills/ok-cosmic/references/adv/form-utils.md +133 -0
  146. package/vendor/kingdee-skills/ok-cosmic/references/adv/operate-chain.md +159 -0
  147. package/vendor/kingdee-skills/ok-cosmic/references/adv/plugin-base.md +218 -0
  148. package/vendor/kingdee-skills/ok-cosmic/references/adv/query-dataset.md +149 -0
  149. package/vendor/kingdee-skills/ok-cosmic/references/adv/request-context.md +88 -0
  150. package/vendor/kingdee-skills/ok-cosmic/references/adv/view-handler.md +157 -0
  151. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-bill.md +76 -0
  152. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-botp.md +70 -0
  153. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-form.md +165 -0
  154. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-import.md +69 -0
  155. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-list.md +227 -0
  156. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-openapi.md +112 -0
  157. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-operation.md +135 -0
  158. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-print.md +65 -0
  159. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-data.md +64 -0
  160. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-form.md +90 -0
  161. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-task.md +62 -0
  162. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-tree-list.md +71 -0
  163. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-workflow.md +82 -0
  164. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-writeback.md +71 -0
  165. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-algo.md +67 -0
  166. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-cache.md +63 -0
  167. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-model-svc.md +82 -0
  168. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-object.md +70 -0
  169. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-entity-model.md +61 -0
  170. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-exception.md +64 -0
  171. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-file.md +63 -0
  172. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-id.md +47 -0
  173. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-lock.md +61 -0
  174. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-log.md +63 -0
  175. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-network-control.md +70 -0
  176. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-orm-access.md +78 -0
  177. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-request-context.md +62 -0
  178. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-threadpool.md +63 -0
  179. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-tx.md +64 -0
  180. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-utils.md +67 -0
  181. package/vendor/kingdee-skills/ok-cosmic/requirements.txt +2 -0
  182. package/vendor/kingdee-skills/ok-cosmic/rules/a-layer-rules.json +24 -0
  183. package/vendor/kingdee-skills/ok-cosmic/rules/anti-patterns.md +48 -0
  184. package/vendor/kingdee-skills/ok-cosmic/rules/cheat-sheet.md +256 -0
  185. package/vendor/kingdee-skills/ok-cosmic/rules/coding-preferences.md +140 -0
  186. package/vendor/kingdee-skills/ok-cosmic/rules/constraints.md +61 -0
  187. package/vendor/kingdee-skills/ok-cosmic/rules/decision-matrix.md +222 -0
  188. package/vendor/kingdee-skills/ok-cosmic/rules/intent-routing.md +94 -0
  189. package/vendor/kingdee-skills/ok-cosmic/rules/platform-baseline.md +69 -0
  190. package/vendor/kingdee-skills/ok-cosmic/rules/post-check.md +109 -0
  191. package/vendor/kingdee-skills/ok-cosmic/scripts/config_loader.py +204 -0
  192. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-api-knowledge.py +910 -0
  193. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-basedata-query.py +359 -0
  194. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-config-check.py +181 -0
  195. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-extpoints-query.py +389 -0
  196. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-form-metadata.py +856 -0
  197. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-check.py +262 -0
  198. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-lint.py +293 -0
  199. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/__init__.py +2 -0
  200. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/base.py +393 -0
  201. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/resource_check.py +176 -0
  202. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/scene_check.py +375 -0
  203. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/style_check.py +434 -0
  204. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/verify_check.py +36 -0
  205. package/vendor/kingdee-skills/ok-cosmic/scripts/route_client.py +186 -0
  206. package/vendor/kingdee-skills/ok-cosmic/scripts/script_utils.py +40 -0
  207. package/vendor/kingdee-skills/ok-cosmic/scripts/sqlite_cache.py +142 -0
  208. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-commons.jar +0 -0
  209. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-features.jar +0 -0
  210. package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic-docs.db +0 -0
  211. package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic.json +13 -0
  212. package/vendor/kingdee-skills/ok-cosmic/setup/setup-mac.sh +18 -0
  213. package/vendor/kingdee-skills/ok-cosmic/setup/setup-windows.bat +53 -0
  214. package/vendor/kingdee-skills/ok-cosmic/setup/setup.jar +0 -0
  215. package/vendor/kingdee-skills/ok-ksql/SKILL.md +81 -0
  216. package/vendor/kingdee-skills/ok-ksql/agents/openai.yaml +7 -0
  217. package/vendor/kingdee-skills/ok-ksql/manifest.json +14 -0
  218. package/vendor/kingdee-skills/ok-ksql/references/ksql-datafix.md +452 -0
  219. package/vendor/kingdee-skills/ok-ksql/scripts/ksql_lint.py +363 -0
@@ -0,0 +1,375 @@
1
+ # -*- coding: utf-8 -*-
2
+ """场景错配检查 (SCENE-*) — 来源: anti-patterns.md 场景错配表"""
3
+
4
+ import re
5
+ from typing import List, Optional, Set, Tuple
6
+
7
+ from .base import (
8
+ LintIssue,
9
+ Severity,
10
+ analyze_java_context,
11
+ analyze_plugin_context,
12
+ classify_lines,
13
+ code_for_structure,
14
+ detect_listener_interfaces,
15
+ detect_plugin_type,
16
+ parse_java,
17
+ )
18
+
19
+
20
+ INITIALIZE_UI_PATTERN = re.compile(
21
+ r"getView\s*\(\)\s*\.\s*"
22
+ r"(setEnable|setVisible|updateView|show\w+|setFocus|setMustInput|setCaption)\s*\("
23
+ )
24
+ INITIALIZE_LISTENER_PATTERN = re.compile(r"add\w*Listener[s]?\s*\(")
25
+ BIND_MUTATION_PATTERN = re.compile(
26
+ r"(?:(?:getModel\s*\(\)|\bmodel)\s*\.\s*"
27
+ r"(setValue|deleteEntryRow|createNewEntryRow|insertEntryRow|batchCreateNewEntryRow|setDataEntity)\s*\()"
28
+ r"|(?:\.\s*setValueFast\s*\()"
29
+ )
30
+ META_TABLE_PATTERN = re.compile(r"\bt_meta_[A-Za-z0-9_]+\b", re.IGNORECASE)
31
+ ENTITY_METADATA_CREATE_PATTERN = re.compile(
32
+ r"EntityMetadataCache\s*\.\s*getDataEntityType\s*\([^)]*\)\s*\.\s*createInstance\s*\("
33
+ )
34
+ # SCENE-012: propertyChanged 中无条件 setValue 检测
35
+ _PC_SETVALUE_PATTERN = re.compile(
36
+ r"(?:getModel\s*\(\)\s*\.\s*setValue|model\s*\.\s*setValue|\.\s*setValueFast)\s*\("
37
+ )
38
+ _PC_GUARD_PATTERN = re.compile(r"getProperty\s*\(\s*\)|getChangeSet\s*\(\s*\)")
39
+
40
+
41
+ def check(filepath: str, lines: List[str]) -> List[LintIssue]:
42
+ """执行场景错配检查,返回问题列表。"""
43
+ issues: List[LintIssue] = []
44
+ listeners = detect_listener_interfaces(lines)
45
+ tree, lang = parse_java(lines)
46
+ method_context, _ = analyze_java_context(lines, tree=tree)
47
+ plugin_context = analyze_plugin_context(lines)
48
+ skip_lines = classify_lines(lines)
49
+
50
+ # 有状态上下文
51
+ _model_alias_vars: Set[str] = set() # 追踪操作插件中 getModel() 赋值的变量名
52
+ current_method: Optional[str] = None
53
+
54
+ # ── 逐行检查 ──
55
+ for i, line in enumerate(lines):
56
+ lineno = i + 1
57
+ code_line = code_for_structure(line)
58
+ method_name = (method_context[i] or "").lower()
59
+ is_op_line = plugin_context[i] == "op"
60
+
61
+ if method_context[i] != current_method:
62
+ _model_alias_vars.clear()
63
+ current_method = method_context[i]
64
+
65
+ # SCENE-001: 操作插件不应调 getView()
66
+ if is_op_line and not skip_lines[i]:
67
+ if re.search(r"this\s*\.\s*getView\s*\(\s*\)", code_line) or re.search(r"getView\(\)", code_line):
68
+ if not re.search(r"(log\.|getContextSample\s*\()", code_line):
69
+ issues.append(LintIssue(
70
+ file=filepath, line=lineno,
71
+ severity=Severity.ERROR,
72
+ rule_id="SCENE-001",
73
+ message="操作插件中调用 getView():操作插件无 UI 上下文",
74
+ fix_hint="使用 log 记录日志或 OpUtils.addErrorMessage() 报告错误",
75
+ source_line=line.strip(),
76
+ ))
77
+
78
+ # SCENE-002: 操作插件不应通过 model 操作
79
+ if is_op_line and not skip_lines[i]:
80
+ if re.search(r"this\s*\.\s*getModel\s*\(\s*\)\s*\.\s*setValue", code_line):
81
+ issues.append(LintIssue(
82
+ file=filepath, line=lineno,
83
+ severity=Severity.ERROR,
84
+ rule_id="SCENE-002",
85
+ message="操作插件中调用 getModel().setValue():操作插件不通过 model 操作",
86
+ fix_hint="直接操作 DynamicObject 数据包: dataEntity.set(\"field\", value)",
87
+ source_line=line.strip(),
88
+ ))
89
+ else:
90
+ # 追踪 model 别名: Type varName = this.getModel() 或 getModel()
91
+ _model_assign = re.search(
92
+ r'\b(\w+)\s*=\s*(?:this\s*\.\s*)?getModel\s*\(\s*\)', code_line
93
+ )
94
+ if _model_assign:
95
+ _model_alias_vars.add(_model_assign.group(1))
96
+ # 检测 model 别名调用 setValue
97
+ for _mvar in _model_alias_vars:
98
+ if re.search(rf'\b{re.escape(_mvar)}\s*\.\s*setValue\s*\(', code_line):
99
+ issues.append(LintIssue(
100
+ file=filepath, line=lineno,
101
+ severity=Severity.ERROR,
102
+ rule_id="SCENE-002",
103
+ message=f"操作插件中通过 model 变量 '{_mvar}' 调用 setValue():操作插件不通过 model 操作",
104
+ fix_hint="直接操作 DynamicObject 数据包: dataEntity.set(\"field\", value)",
105
+ source_line=line.strip(),
106
+ ))
107
+ break
108
+
109
+ # SCENE-003: registerListener 中读数据
110
+ if method_name == "registerlistener" and re.search(r"(getModel|getValue)\s*\(", code_line) and not skip_lines[i]:
111
+ issues.append(LintIssue(
112
+ file=filepath, line=lineno,
113
+ severity=Severity.WARNING,
114
+ rule_id="SCENE-003",
115
+ message="在 registerListener 中调用 getValue():此时数据尚未绑定",
116
+ fix_hint="推迟到 afterBindData() 中处理",
117
+ source_line=line.strip(),
118
+ ))
119
+
120
+ # SCENE-006: initialize 中注册监听
121
+ if method_name == "initialize" and INITIALIZE_LISTENER_PATTERN.search(code_line):
122
+ issues.append(LintIssue(
123
+ file=filepath, line=lineno,
124
+ severity=Severity.ERROR,
125
+ rule_id="SCENE-006",
126
+ message="禁止在 initialize() 中注册监听事件",
127
+ fix_hint="将 addXxxListener(...) 挪到 registerListener() 中",
128
+ source_line=line.strip(),
129
+ ))
130
+
131
+ # SCENE-007: initialize 中做 UI 状态逻辑
132
+ if method_name == "initialize" and INITIALIZE_UI_PATTERN.search(code_line):
133
+ issues.append(LintIssue(
134
+ file=filepath, line=lineno,
135
+ severity=Severity.ERROR,
136
+ rule_id="SCENE-007",
137
+ message="禁止在 initialize() 中处理 UI 状态或弹窗逻辑",
138
+ fix_hint="将界面控制逻辑挪到 afterBindData() 或正确的 UI 事件中",
139
+ source_line=line.strip(),
140
+ ))
141
+
142
+ # SCENE-008: before/afterBindData 中修改数据对象
143
+ if method_name in {"beforebinddata", "afterbinddata"} and BIND_MUTATION_PATTERN.search(code_line):
144
+ issues.append(LintIssue(
145
+ file=filepath, line=lineno,
146
+ severity=Severity.ERROR,
147
+ rule_id="SCENE-008",
148
+ message="禁止在 beforeBindData()/afterBindData() 中修改数据对象",
149
+ fix_hint="将 setValue/分录增删等数据变更挪到 createNewData、afterCreateNewData、propertyChanged 或正确的业务事件",
150
+ source_line=line.strip(),
151
+ ))
152
+
153
+ # SCENE-009: 直接访问平台元数据表
154
+ if META_TABLE_PATTERN.search(code_line) and not skip_lines[i]:
155
+ issues.append(LintIssue(
156
+ file=filepath, line=lineno,
157
+ severity=Severity.ERROR,
158
+ rule_id="SCENE-009",
159
+ message="业务代码禁止直接访问平台元数据表 t_meta_xxx",
160
+ fix_hint="使用元数据脚本或平台 API 获取字段/实体信息,不要直接查 t_meta_xxx",
161
+ source_line=line.strip(),
162
+ ))
163
+
164
+ # SCENE-010: 用其他实体 createInstance() 构造引用对象
165
+ if ENTITY_METADATA_CREATE_PATTERN.search(code_line):
166
+ issues.append(LintIssue(
167
+ file=filepath, line=lineno,
168
+ severity=Severity.ERROR,
169
+ rule_id="SCENE-010",
170
+ message="直接用 EntityMetadataCache.getDataEntityType(...).createInstance() 构造对象,容易出现引用类型不一致",
171
+ fix_hint="优先通过当前实体属性复杂类型或当前实体元数据 createInstance()",
172
+ source_line=line.strip(),
173
+ ))
174
+
175
+ # ── 方法级检查: propertyChanged 无条件 setValue ──
176
+ _check_unguarded_setvalue_in_property_changed(filepath, lines, method_context, skip_lines, issues)
177
+
178
+ # ── 文件级检查: Listener 注册 ──
179
+ if listeners:
180
+ has_register = any(
181
+ re.search(r"void\s+registerListener\s*\(", l) for l in lines
182
+ )
183
+ if not has_register:
184
+ # SCENE-004: 实现了 Listener 但没有 registerListener 方法
185
+ issues.append(LintIssue(
186
+ file=filepath, line=1,
187
+ severity=Severity.WARNING,
188
+ rule_id="SCENE-004",
189
+ message=f"实现了 Listener 接口 ({', '.join(listeners)}) 但未找到 registerListener 方法",
190
+ fix_hint="在 registerListener() 中调用 addXxxListener() 注册监听",
191
+ ))
192
+ else:
193
+ # SCENE-005: 有 registerListener 但没有 addXxxListener 调用
194
+ # 使用 AST 树精确定位 registerListener 方法体
195
+ has_add_listener = False
196
+ try:
197
+ import tree_sitter
198
+ q = tree_sitter.Query(lang, "(method_declaration name: (identifier) @name body: (block) @body)")
199
+ for match in q.matches(tree.root_node):
200
+ if len(match) > 1 and isinstance(match[1], dict):
201
+ match_dict = match[1]
202
+ m_name_nodes = match_dict.get("name", [])
203
+ m_body_nodes = match_dict.get("body", [])
204
+ if m_name_nodes and m_body_nodes:
205
+ if m_name_nodes[0].text.decode('utf-8') == "registerListener":
206
+ raw_body_text = m_body_nodes[0].text.decode('utf-8')
207
+ clean_body_lines = [code_for_structure(l) for l in raw_body_text.splitlines()]
208
+ body_text = "\n".join(clean_body_lines)
209
+ if re.search(r"add\w*Listener[s]?\s*\(", body_text):
210
+ has_add_listener = True
211
+ except Exception:
212
+ # 降级:如果 AST 失败,假设通过避免误报
213
+ has_add_listener = True
214
+
215
+ if not has_add_listener:
216
+ issues.append(LintIssue(
217
+ file=filepath, line=1,
218
+ severity=Severity.WARNING,
219
+ rule_id="SCENE-005",
220
+ message=f"实现了 Listener 接口 ({', '.join(listeners)}) 但 registerListener 中未调用 addXxxListener()",
221
+ fix_hint="在 registerListener() 中调用对应的 addXxxListener(this) 注册",
222
+ ))
223
+
224
+ # ── 文件级检查: 继承型插件 @Override 不调 super ──
225
+ is_op, is_ui, is_other = detect_plugin_type(lines)
226
+ is_inheritable = is_op or is_ui or is_other
227
+ if is_inheritable:
228
+ _check_missing_super(filepath, lines, plugin_context, issues, tree=tree, lang=lang)
229
+
230
+ return issues
231
+
232
+
233
+ def _check_unguarded_setvalue_in_property_changed(
234
+ filepath: str, lines: List[str],
235
+ method_context: List, skip_lines: List[bool], issues: List[LintIssue],
236
+ ):
237
+ """SCENE-012: propertyChanged 中调用 setValue 但未判断 getProperty() 或 getChangeSet(),死循环风险。"""
238
+ # 收集 propertyChanged 方法体的行范围
239
+ ranges: List[Tuple[int, int]] = []
240
+ start: int = -1
241
+ for i, mc in enumerate(method_context):
242
+ if mc and mc.lower() == "propertychanged":
243
+ if start < 0:
244
+ start = i
245
+ else:
246
+ if start >= 0:
247
+ ranges.append((start, i))
248
+ start = -1
249
+ if start >= 0:
250
+ ranges.append((start, len(lines)))
251
+
252
+ for s, e in ranges:
253
+ has_set_value = False
254
+ has_guard = False
255
+ first_sv_line: int = -1
256
+ for i in range(s, e):
257
+ if skip_lines[i]:
258
+ continue
259
+ code = code_for_structure(lines[i])
260
+ if _PC_SETVALUE_PATTERN.search(code):
261
+ if not has_set_value:
262
+ first_sv_line = i
263
+ has_set_value = True
264
+ if _PC_GUARD_PATTERN.search(code):
265
+ has_guard = True
266
+ if has_set_value and not has_guard:
267
+ issues.append(LintIssue(
268
+ file=filepath, line=first_sv_line + 1,
269
+ severity=Severity.ERROR,
270
+ rule_id="SCENE-012",
271
+ message="propertyChanged 中调用 setValue 但未判断 e.getProperty().getName(),可能导致死循环(栈溢出)",
272
+ fix_hint="先用 e.getProperty().getName().equals(\"目标字段\") 守卫,赋值前比对新旧值避免无限递归",
273
+ source_line=lines[first_sv_line].strip(),
274
+ ))
275
+
276
+
277
+ # 继承型插件生命周期方法(需要调 super 的方法名,全小写)
278
+ _LIFECYCLE_METHODS = {
279
+ "initialize", "registerlistener", "preopenform",
280
+ "createnewdata", "aftercreatenewdata", "loaddata", "afterloaddata",
281
+ "beforebinddata", "afterbinddata", "aftercopydata",
282
+ "propertychanged", "beforedooperation", "afterdooperation",
283
+ "beforeitemclick", "itemclick", "beforeclick", "click",
284
+ "beforef7select", "confirmcallback", "closedcallback",
285
+ "clientcallback", "beforeclosed", "customevent",
286
+ "afteraddrow", "afterdeleterow", "afterdeleteentry", "destory",
287
+ "onpreparepropertys", "onaddvalidators",
288
+ "beforeexecuteoperationtransaction", "beginoperationtransaction",
289
+ "endoperationtransaction", "afterexecuteoperationtransaction",
290
+ "onreturnoperation",
291
+ "setfilter", "beforedoselectrow",
292
+ }
293
+
294
+ _OVERRIDE_PATTERN = re.compile(r"@Override")
295
+ _METHOD_NAME_PATTERN = re.compile(
296
+ r"(?:public|protected)\s+\w[\w<>\[\], ?.]*\s+([A-Za-z_]\w*)\s*\("
297
+ )
298
+ _SUPER_CALL_PATTERN_TEMPLATE = r"\bsuper\s*\.\s*{method}\s*\("
299
+
300
+
301
+ def _check_missing_super(filepath: str, lines: List[str],
302
+ plugin_context: List, issues: List[LintIssue],
303
+ tree=None, lang=None):
304
+ """检测继承型插件中 @Override 生命周期方法是否遗漏 super 调用。"""
305
+ try:
306
+ import tree_sitter
307
+ if tree is None or lang is None:
308
+ tree, lang = parse_java(lines)
309
+
310
+ q = tree_sitter.Query(lang, """
311
+ (method_declaration
312
+ name: (identifier) @name
313
+ body: (block) @body
314
+ ) @method
315
+ """)
316
+
317
+ for match in q.matches(tree.root_node):
318
+ if len(match) < 2 or not isinstance(match[1], dict):
319
+ continue
320
+ match_dict = match[1]
321
+
322
+ method_nodes = match_dict.get("method", [])
323
+ if not method_nodes: continue
324
+ method_node = method_nodes[0]
325
+
326
+ # Check @Override
327
+ is_override = False
328
+ for child in method_node.children:
329
+ if child.type == "modifiers":
330
+ for mod in child.children:
331
+ if mod.type == "marker_annotation" and "Override" in mod.text.decode('utf-8'):
332
+ is_override = True
333
+
334
+ if not is_override:
335
+ continue
336
+
337
+
338
+ # Get Method Name
339
+ name_nodes = match_dict.get("name", [])
340
+ if not name_nodes: continue
341
+ method_name = name_nodes[0].text.decode('utf-8')
342
+
343
+ if method_name.lower() not in _LIFECYCLE_METHODS:
344
+ continue
345
+
346
+ # Check Plugin Context for this method
347
+ # Just take the context of the line where method name is
348
+ method_line = name_nodes[0].start_point[0]
349
+ if method_line < len(plugin_context) and plugin_context[method_line] not in {"op", "ui", "other"}:
350
+ continue
351
+
352
+ # Check if super.methodName() exists in the body
353
+ body_nodes = match_dict.get("body", [])
354
+ if not body_nodes: continue
355
+ raw_body_text = body_nodes[0].text.decode('utf-8')
356
+
357
+ clean_body_lines = [code_for_structure(l) for l in raw_body_text.splitlines()]
358
+ body_text = "\n".join(clean_body_lines)
359
+
360
+ super_pattern = re.compile(
361
+ _SUPER_CALL_PATTERN_TEMPLATE.format(method=re.escape(method_name))
362
+ )
363
+
364
+ if not super_pattern.search(body_text):
365
+ issues.append(LintIssue(
366
+ file=filepath, line=method_line + 1,
367
+ severity=Severity.WARNING,
368
+ rule_id="SCENE-011",
369
+ message=f"继承型插件 @Override {method_name}() 未调用 super.{method_name}(),基类初始化逻辑可能不执行",
370
+ fix_hint=f"在方法体首行添加 super.{method_name}(...);接口型插件(如 IWorkflowPlugin)无需此调用",
371
+ source_line=method_name,
372
+ ))
373
+ except Exception:
374
+ # 降级:如果 AST 失败,不做检查,避免由于解析失败导致的误报
375
+ pass