Files
Idea-Plugin/README.md
T
2026-05-08 17:14:51 +08:00

211 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Idea-PluginIntelliJ IDEA 插件)
在 IDEA 内提供:**Proto → Java 命令类**、**MySQL → JPA 实体**、**Java 类 ↔ JSON**、**按项目保存的备忘录**、**提交前本机时间校验**。
---
## 功能一览
| 功能 | 主要入口 | 说明 |
|------|----------|------|
| Proto 转 Java | 右键 `.proto`、项目树、**Tools** | 从 proto 生成 `@Cmd` 命令类 |
| mysql 转 Jpa | 右键**文件夹**、**Tools** | 连接 MySQL,多表生成 JPA 实体 |
| Java → JSON | 类名上 **Alt+Enter**、编辑器右键 | 按字段类型生成带默认值的 JSON |
| Json 转 java | 右键**文件夹**、**Tools** | 从 JSON 生成 Java Bean 源文件 |
| 我的自定义备忘录 | **Tools**、工具窗口 | 按项目保存备忘录 |
| 提交前时间校验 | 提交 / 提交并推送 | 本机时间与网络时间偏差过大时警告 |
---
## 1. Proto 转 Java
**做什么**:从 `cmd_rpc.proto`(及同目录可选的 `pb_service.proto`)解析 `ServiceNService``rpc`,在指定目录生成与 **comm-framework** 风格一致的 `@Cmd` + `AbstractTypedPbCommand` Java 类。
**怎么用**
1. 打开符合约定的 `.proto`(可与 `pb_service.proto` 同目录)。
2. **Proto转Java**(编辑器或项目树右键选中 `.proto`,或 **Tools** 菜单)。
3. 在对话框中勾选 RPC、选择输出目录(如 `.../src/main/java/.../cmd/cmds`)。
4. 确认生成;已存在的同名 `.java` 会**跳过**。
**实现要点**
- 入口:`ProtoCmdGeneratorAction`;对话框 `GenerateCmdDialog`;生成逻辑 `ProtoFileParser``JavaCommandGenerator` 等。
- 输出:通过 `PsiFileFactory` + `WriteCommandAction` 在目标目录创建 `.java` 文件。
**约定**Proto
- **Service 命名**`Service1Service``Service2Service`、…
- **Method 枚举**:同文件内 `ServiceN_Method`,去掉 `Default*` 后按枚举值从小到大与同一 service 内 **rpc 声明顺序** 对应。
- **PbService**:同目录 `pb_service.proto``enum PbService``= N` 的项名;缺失时回退为 `Service_N`
---
## 2. mysql 转 Jpa
**做什么**:连接 MySQL,列出库表(支持搜索与多选),按表结构生成带 **`jakarta.persistence`** 注解的实体类(`@Entity``@Table``@Id``@Column` 等;复合主键生成 `@IdClass`)。
**怎么用**
1.**Java 源码目录**(如 `.../src/main/java/你的包路径`)上**右键文件夹**打开对话框,或从 **Tools** 打开(需在对话框中理解输出目录与包名推断规则)。
2. 填写 JDBC(**必须含库名**,例如 `host:3306/your_db` 或完整 `jdbc:mysql://.../your_db?...`)、用户名、密码。
3. **查询表** → 搜索 / 多选表 → **生成 Java 实体**
**实现要点**
- 入口:`MysqlEntityFromFolderAction`;对话框与写文件:`mysql` 包下 `MysqlEntityDialog`、实体生成器等。
- JDBC:插件依赖 `mysql-connector-j`URL 须包含库名。
- 包名:优先根据所选目录相对 `src/main/java` 的路径推断(`PackageInference`)。
- 若目标工程仍为 Spring Boot 2 / `javax.persistence`,生成代码中的包名需自行替换或改生成器。
---
## 3. Java 类 → JSON(默认值)
**做什么**:根据当前 Java 类的**非 static 实例字段**(含继承字段)生成一段 **JSON**,各类型使用约定**默认值**(数字 0、布尔 false、字符串 `""`、集合 `[]`、Map `{}`、嵌套类型递归为对象;循环引用处为 `null` 等)。
**怎么用**
1. **推荐**:光标放在**类声明上的类名**(例如 `public class Foo` 中的 `Foo`),按 **Alt+Enter**,选择 **「是否生成 JSON(默认值)…」**。
2. 在确认对话框中选 **是**
3. 在结果弹窗中查看 JSON,可点击 **「复制到剪贴板」**。
**备选**:光标在类体内任意位置时,编辑器 **右键****「生成类JSON(默认值)」**,流程相同(先确认再弹窗)。
**实现要点**
- 意图:`ClassToJsonIntention`(注册于 `plugin.xml``intentionAction`,说明见 `intentionDescriptions/ClassToJsonIntention/`)。
- 编辑器菜单:`GenerateClassJsonEditorAction`
- 构建 JSON`JavaClassToJsonBuilder`(PSI 字段与类型 + Gson 格式化);展示:`ShowJsonResultDialog`
---
## 4. Json 转 java
**做什么**:根据输入的 **JSON 对象**(根节点必须是 `{}`)和 **Java 类名**,在选定目录生成一个 **Java Bean** 源文件:`private` 字段 + getter/setter;嵌套对象生成 **静态内部类**;数组字段推断为 `List<…>`(元素类型主要依据**数组第一个元素**)。
**怎么用**
1. 在项目树中**右键目标文件夹**(一般为 `src/main/java/...` 下某包目录),或使用 **Tools****Json转java**(须已能确定输出目录;若未选文件夹会提示)。
2. 填写 **类名**(不含 `.java`)、**包名**(默认按目录用 `PackageInference` 推断)。
3. 粘贴 **JSON**(根为对象)。
4. 确定后生成 `类名.java`;若文件已存在则**不覆盖**并提示。
**实现要点**
- 入口:`JsonToJavaAction`;对话框:`JsonToJavaDialog`;解析与代码生成:`JsonToJavaGenerator`Gson 解析);字段名规则复用 `mysql/JavaNames`
- 依赖:Gson`build.gradle.kts`)。
---
## 5. 我的自定义备忘录
**做什么**:右侧工具窗口,对当前 **项目** 做备忘录的增删改(新建、编辑后保存、删除)。
**怎么用**
1. **Tools****我的自定义备忘录**;或在 **View → Tool Windows** 中找到同名窗口。
2. **新建** → 填写标题与正文 → **保存**;选中条目可 **删除**
3. 切换列表项前请先 **保存** 当前编辑,避免未写入的修改被覆盖。
**实现要点**
- 工具窗口:`memo/MemoToolWindowFactory` 等;持久化:`MemoProjectService` + `.idea/protoPluginMemos.xml`
- 工具窗口 ID`MyCustomMemo`(与 `plugin.xml` 中一致)。
---
## 6. 提交前时间校验(Commit / Commit & Push
**做什么**:在 **提交****提交并推送** 前,用 HTTP 响应头里的 `Date` 作为参考时间,与 **本机系统时间** 比较;偏差超过 **1 分钟** 时弹出警告,用户可选择继续或取消本次提交。
**怎么用**
- 正常走 IDE 的 **Commit** / **Commit and Push** 即可;无单独菜单。若本机时间与网络时间相差过大,会看到警告对话框。
**实现要点**
- `CommitTimeCheckinHandlerFactory` 注册 `CheckinHandler`;实际校验在 Kotlin `TimeSkewCommitCheckHandler``CommitCheck`**`ExecutionOrder.EARLY`**)。
- 使用 EARLY 是为避免默认 LATE 检查在部分场景下触发 **ABORTED → Cancelled**,表现为提交界面异常或文件被回退。
- 无法访问外网、拿不到参考时间时:**不拦截**。Shelf、Create Patch 等本地提交执行器通常不跑该校验。
---
## 环境
- JDK **17**
- IntelliJ IDEA **2023.3.x Ultimate**(与 `sinceBuild` 233 等对齐);`gradle.properties` 可配置 `ideaLocalPath` 指向本机安装目录,`runIde` 沙盒使用该 IDEA。若路径不同请修改;未配置时 Gradle 会尝试在线解析 `2023.3` + `IU`
- **运行沙箱**:若仓库含 Gradle Wrapper,可用 `./gradlew runIde`;若无 wrapper,可用本机已安装的 Gradle 执行相同任务(见下节)。
### 国内镜像(已配置)
- **Gradle Wrapper**:若存在 `gradle/wrapper/gradle-wrapper.properties`,可使用腾讯云等镜像与合适发行版(如 `gradle-8.5-all.zip``bin.zip`)。
- **Maven / 插件仓库**`settings.gradle.kts``build.gradle.kts` 已优先阿里云等公共仓库。
- **IntelliJ Platform SDK**:国内常因 CloudFront 导致 `UnknownHostException`**推荐配置 `ideaLocalPath``IDEA_LOCAL_PATH`**,避免下载 `ideaIU`
### `ideaLocalPath` 在 Program Files 时:拒绝访问
`gradle-intellij-plugin` 使用本机 IDE 时可能在安装目录写入 Ivy/builtin 元数据;`C:\Program Files\…` 可能不可写。
**处理**:将 IDEA 装到用户目录(Toolbox)、或复制到可写盘,再把 `ideaLocalPath` 指到该根目录(含 `lib``plugins`)。
### Gradle JVM
`gradle-intellij-plugin` 1.17.x 需 **JDK 11+**;本项目源码为 **17**。IDEA 中 **Settings → Gradle → Gradle JVM** 请选择 17。
### runIde 启动日志里的告警/异常(多与本插件代码无关)
| 现象 | 常见原因 | 建议处理 |
|------|----------|----------|
| `VFS wasn't safely shut down``Content storage... broken``LocalHistory is lost` | 上次沙箱里的 IDEA **未正常退出**,虚拟文件系统缓存损坏 | 清沙箱后重跑(见下) |
| `GradleJvmSupportMatrix` + `IllegalArgumentException: 25``JavaVersion.parse` | 沙箱内 **Gradle 插件** 持久化配置损坏,或与 2023.3 内置解析逻辑冲突 | 清沙箱后重跑 |
| `LoadingState` / `Should be called at least in the state COMPONENTS_LOADED``Registry`) | **平台**在极早启动阶段被 VFS 刷新等并发触发,属 IDE 内部时序问题 | 一般可忽略;清沙箱可减轻连带问题 |
| `Watch roots should be absolute: src/main/java` | **当前打开的业务工程**里模块源根被记成相对路径,`.iml`/导入异常 | 在**该工程**中 **Gradle/Maven Reload** 或重新导入 |
| `Project ... not trusted enough` | 沙箱安全策略未信任项目 | 在沙箱 IDEA 里对该工程点 **Trust Project** |
**清沙箱(推荐):**
```bash
./gradlew cleanIdeaSandbox runIde
```
或先删目录再运行:`build/idea-sandbox`Windows 下路径为 `build\idea-sandbox`)。
**每次 runIde 前自动清沙箱(可选,会丢掉沙箱里的设置与最近打开的工程记录):**
```bash
./gradlew runIde -PfreshSandbox
```
---
## 构建插件 ZIP
```bash
./gradlew buildPlugin
```
若无 `gradlew`,使用本机 Gradle
```bash
gradle buildPlugin
```
产物在 **`build/distributions/`**(一般为 `Idea-Plugin-<version>.zip`),在 IDEA **Settings → Plugins → Install Plugin from Disk** 安装。
**`build` / `buildPlugin``:buildSearchableOptions` 阶段报错**(如 `sun.font.Font2D.getTypographicFamilyName` / `NoSuchMethodError`),多半是 **跑该任务的 Java 与 IDEA 自带 JBR 版本不一致**。本仓库在 `build.gradle.kts``tasks { named("buildSearchableOptions") { enabled = false } }` 中禁用了该任务;一般插件不需要生成该项。若你必须开启,请删除上述配置并让 **Gradle JVM** 使用安装目录下的 **`jbr`** 再试。
---
## 项目结构(主要源码)
| 路径 | 说明 |
|------|------|
| `ProtoCmdGeneratorAction` / `GenerateCmdDialog` / `JavaCommandGenerator` | Proto → Cmd 生成 |
| `MysqlEntityFromFolderAction` / `mysql/*` | MySQL 元数据与 JPA 源码生成 |
| `json/*` | Java→JSONPSI + Gson)、JSON→Java(对话框 + 生成器)、意图与编辑器 Action |
| `PackageInference` | 由目录路径推断 Java 包名 |
| `memo/*` | 备忘录状态与工具窗口 UI |
| `vcs/*` | 提交前时间校验(`CheckinHandlerFactory` + Kotlin `CommitCheck` EARLY |
| `META-INF/plugin.xml` | 插件描述、Action、Tool Window、Intention、Project Service |