|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +## 项目概述 |
| 4 | + |
| 5 | +**dt-sql-parser** 是一个基于 [ANTLR4](https://github.com/antlr/antlr4) 构建的 SQL 解析器库,面向 **大数据** 领域。它提供以下功能: |
| 6 | + |
| 7 | +- SQL 语法校验 |
| 8 | +- AST 遍历(Visitor / Listener 模式) |
| 9 | +- 代码补全(基于 [antlr4-c3](https://github.com/mike-lischke/antlr4-c3)) |
| 10 | +- 实体提取(表、列等) |
| 11 | +- SQL 语句拆分 |
| 12 | + |
| 13 | +**支持的 SQL 方言**:MySQL、Flink、Spark、Hive、PostgreSQL、Trino、Impala。 |
| 14 | + |
| 15 | +## 技术栈 |
| 16 | + |
| 17 | +| 类别 | 说明 | |
| 18 | +| -------------- | ----------------------------------------------------- | |
| 19 | +| 语言 | TypeScript(目标 ES6,模块 ESNext) | |
| 20 | +| 运行环境 | Node.js >= 18 | |
| 21 | +| 包管理器 | pnpm 9.7.0 | |
| 22 | +| 构建工具 | `tsc`(TypeScript 编译器) | |
| 23 | +| 测试框架 | Jest(配合 `@swc/jest` 转换器) | |
| 24 | +| 解析器生成 | ANTLR4,通过 `antlr4ng` + `antlr4ng-cli` | |
| 25 | +| 代码补全 | `antlr4-c3` | |
| 26 | +| 代码格式化 | Prettier、`antlr-format-cli`(用于 `.g4` 文件) | |
| 27 | +| Git Hooks | Husky + lint-staged + commitlint | |
| 28 | + |
| 29 | +## 仓库结构 |
| 30 | + |
| 31 | +``` |
| 32 | +dt-sql-parser/ |
| 33 | +├── src/ |
| 34 | +│ ├── grammar/ # ANTLR4 .g4 语法文件(每个方言一个子目录) |
| 35 | +│ ├── lib/ # 从 .g4 文件生成的 Lexer/Parser/Listener/Visitor |
| 36 | +│ ├── parser/ # SQL Parser 类实现 |
| 37 | +│ │ ├── common/ # 基类(BasicSQL)、工具方法、共享类型 |
| 38 | +│ │ ├── mysql/ # MySQL 专属解析器、实体收集器等 |
| 39 | +│ │ ├── flink/ |
| 40 | +│ │ ├── spark/ |
| 41 | +│ │ ├── hive/ |
| 42 | +│ │ ├── postgresql/ |
| 43 | +│ │ ├── trino/ |
| 44 | +│ │ └── impala/ |
| 45 | +│ ├── locale/ # 国际化资源 |
| 46 | +│ └── index.ts # 公共 API 导出 |
| 47 | +├── test/ # 单元测试(结构与 src/ 对应) |
| 48 | +│ ├── parser/ # 按方言组织的测试 |
| 49 | +│ │ ├── mysql/ |
| 50 | +│ │ │ ├── syntax/ # 语法规则测试 |
| 51 | +│ │ │ ├── suggestion/ # 代码补全测试 |
| 52 | +│ │ │ └── contextCollect/ # 实体收集测试 |
| 53 | +│ │ └── ... |
| 54 | +│ └── common/ # 共享测试工具 |
| 55 | +├── benchmark/ # 性能基准测试 |
| 56 | +├── scripts/ # 构建/发布实用脚本 |
| 57 | +├── gen/ # 生成产物 |
| 58 | +├── dist/ # 编译输出(npm 包) |
| 59 | +├── .husky/ # Git Hook 配置 |
| 60 | +├── package.json |
| 61 | +├── tsconfig.json |
| 62 | +├── jest.config.js |
| 63 | +└── CONTRIBUTING.md # 贡献指南(新增方言步骤) |
| 64 | +``` |
| 65 | + |
| 66 | +## 核心开发命令 |
| 67 | + |
| 68 | +```bash |
| 69 | +pnpm install # 安装依赖 |
| 70 | +pnpm antlr4 # 从所有 .g4 文件生成 TS |
| 71 | +pnpm antlr4 --lang mysql # 为指定方言生成 |
| 72 | +pnpm build # 编译 TypeScript(rm -rf dist && tsc) |
| 73 | +pnpm test # 运行 Jest 单元测试 |
| 74 | +pnpm benchmark # 运行性能基准测试 |
| 75 | +pnpm check-types # 对 src/ 和 test/ 进行类型检查 |
| 76 | +pnpm format # 用 Prettier 格式化所有文件 |
| 77 | +pnpm format-g4 # 格式化 .g4 语法文件 |
| 78 | +pnpm prettier-check # 检查格式是否符合要求(不修改) |
| 79 | +``` |
| 80 | + |
| 81 | +## 架构说明 |
| 82 | + |
| 83 | +### Parser 类层级 |
| 84 | + |
| 85 | +``` |
| 86 | +BasicSQL (src/parser/common/) |
| 87 | + ├── MySQL |
| 88 | + ├── FlinkSQL |
| 89 | + ├── SparkSQL |
| 90 | + ├── HiveSQL |
| 91 | + ├── PostgreSQL |
| 92 | + ├── TrinoSQL |
| 93 | + └── ImpalaSQL |
| 94 | +``` |
| 95 | + |
| 96 | +每个方言的 Parser 类(例如 `src/parser/mysql/index.ts` 中的 `MySQL`)继承自 `BasicSQL`,并实现以下方法: |
| 97 | + |
| 98 | +- `createLexerFromCharStream()` — 创建 ANTLR4 Lexer |
| 99 | +- `createParserFromTokenStream()` — 创建 ANTLR4 Parser |
| 100 | +- `splitListener` getter — 返回用于语句拆分的 `SQLSplitListener` |
| 101 | +- `createEntityCollector()` — 返回用于上下文/实体提取的 `SQLEntityCollector` |
| 102 | +- `processCandidates()` / `preferredRules()` — 代码补全逻辑(antlr4-c3) |
| 103 | + |
| 104 | +### 每方言模块结构 |
| 105 | + |
| 106 | +每个 `src/parser/<dialect>/` 目录包含: |
| 107 | + |
| 108 | +| 文件 | 用途 | |
| 109 | +| ------------------------------------------- | --------------------------------------------- | |
| 110 | +| `index.ts` | 主解析器类,继承 `BasicSQL` | |
| 111 | +| `<dialect>EntityCollector.ts` | 从 AST 中提取表、列、函数等实体 | |
| 112 | +| `<dialect>SplitListener.ts` | 通过分号/AST 拆分多语句 SQL | |
| 113 | +| `<dialect>ErrorListener.ts` | 自定义语法错误处理 | |
| 114 | +| `<dialect>SemanticContextCollector.ts` | 收集语义上下文(如 `isStatementBeginning`) | |
| 115 | + |
| 116 | +### 语法文件 → 代码生成流程 |
| 117 | + |
| 118 | +1. `.g4` 文件存放在 `src/grammar/<dialect>/` 目录 |
| 119 | +2. 执行 `pnpm antlr4 [--lang <dialect>]` 生成: |
| 120 | + - `src/lib/<dialect>/<Dialect>Lexer.ts` |
| 121 | + - `src/lib/<dialect>/<Dialect>Parser.ts` |
| 122 | + - `src/lib/<dialect>/<Dialect>ParserListener.ts` |
| 123 | + - `src/lib/<dialect>/<Dialect>ParserVisitor.ts` |
| 124 | +3. `src/parser/<dialect>/` 中的 Parser 类消费这些生成的文件 |
| 125 | + |
| 126 | +### 语法规则约定 |
| 127 | + |
| 128 | +- 根规则必须命名为 `program` |
| 129 | +- 支持解析多条 SQL 语句 |
| 130 | +- 关键字规则前缀为 `KW_`(例如 `KW_SELECT`) |
| 131 | +- 不区分大小写的方言启用 case-insensitive 选项 |
| 132 | + |
| 133 | +## 公共 API(来自 `src/index.ts`) |
| 134 | + |
| 135 | +**类**:`MySQL`、`FlinkSQL`、`SparkSQL`、`HiveSQL`、`PostgreSQL`、`TrinoSQL`、`ImpalaSQL` |
| 136 | + |
| 137 | +**Listener/Visitor 类型**:`MySqlParserListener`、`MySqlParserVisitor` 等(每个方言一对) |
| 138 | + |
| 139 | +**枚举**:`EntityContextType`、`StmtContextType` |
| 140 | + |
| 141 | +**类型**:`CaretPosition`、`Suggestions`、`SyntaxSuggestion`、`WordRange`、`TextSlice`、`SyntaxError`、`ParseError`、`ErrorListener`、`StmtContext`、`EntityContext`、`CommonEntityContext`、`ColumnEntityContext`、`FuncEntityContext` |
| 142 | + |
| 143 | +## 测试规范 |
| 144 | + |
| 145 | +- 测试文件结构与 `src/` 对应,位于 `test/parser/<dialect>/` |
| 146 | +- 子目录:`syntax/`(语法)、`suggestion/`(补全)、`contextCollect/`(实体收集) |
| 147 | +- 使用 Jest 配合 `@swc/jest` 实现快速编译 |
| 148 | +- 自定义匹配器定义在 `test/matchers.ts` |
| 149 | +- 运行命令:`pnpm test` |
| 150 | + |
| 151 | +## 新增 SQL 方言(步骤概要) |
| 152 | + |
| 153 | +1. 在 `src/grammar/<name>/` 下添加 `.g4` 文件(PascalCase 命名,根规则 = `program`,关键字 = `KW_*`) |
| 154 | +2. 执行 `pnpm antlr4 --lang <name>` → 生成 `src/lib/<name>/` |
| 155 | +3. 创建 `src/parser/<name>/index.ts` 继承 `BasicSQL` |
| 156 | +4. 在 `test/parser/<name>/` 下添加测试(lexer、visitor、listener、validate) |
| 157 | +5. 实现 `SQLSplitListener` → 添加 `splitListener` getter |
| 158 | +6. 实现代码补全 → `processCandidates` + `preferredRules`,并在 `suggestion/` 下添加测试 |
| 159 | +7. 实现 `SQLEntityCollector` + `createEntityCollector()`,并在 `contextCollect/` 下添加测试 |
| 160 | +8. 在 `src/parser/index.ts` 和 `src/index.ts` 中导出新类 |
| 161 | + |
| 162 | +## AI Agent 注意事项 |
| 163 | + |
| 164 | +- 修改 `.g4` 文件后 **必须** 执行 `pnpm antlr4`,确保 `src/lib/` 中的生成文件保持同步 |
| 165 | +- **不要** 手动编辑 `src/lib/` 中的文件 —— 它们是由 `.g4` 自动生成的 |
| 166 | +- 语法文件遵循 ANTLR4 约定;关键字规则必须带有 `KW_` 前缀 |
| 167 | +- 项目使用 `antlr4ng`(非 Java antlr4 运行时)作为 TypeScript 目标 |
| 168 | +- 代码补全依赖 `antlr4-c3`;修改补全逻辑前先了解该库 |
| 169 | +- 实体收集器(`SQLEntityCollector`)是实现丰富代码补全的关键 —— 需理解作用域深度和 `isAccessible` 逻辑 |
| 170 | +- 位置/范围约定:行号从 1 开始,列号从 1 开始,索引从 0 开始 |
| 171 | +- Prettier 格式化通过 husky + lint-staged 在提交时强制执行 |
0 commit comments