贡献
如果您想为本项目贡献代码,可以通过在 GitHub 上复刻仓库并发送拉取请求 (PR) 来实现。
提交代码时,请尽力遵循现有的约定和样式,以保持代码尽可能具有可读性。
在您的代码被项目接受之前,您还必须签署 个人贡献者许可协议 (CLA)。
SQLDelight
如果您想开始参与贡献,请参阅下方根据您想贡献的 SQLDelight 部分提供的特定指南。如果您仍然不确定,请在您正在查看的问题中留言,说明您卡在哪里,我们会在那里进行回复——或者为您尝试做的事情创建一个问题并开始讨论。
IDE 插件
如果您想修复错误或扩展 IDE,代码更改通常会发生在 sqldelight-idea-plugin 模块中。您可以使用 ./gradlew runIde 任务测试您的更改,并可以使用 ./gradlew runIde --debug-jvm 进行实时调试。
如果您在 IDE 中遇到错误但在示例项目中无法复现,您可以对您的 IDE 进行实时调试。为此,您需要安装第二个 IntelliJ。您可以通过 Toolbox 来实现:滚动到 IDE 列表底部并选择不同版本的 IntelliJ。
在您想使用调试器的 IDE 中,检出 SQLDelight 仓库,然后创建一个新的 Remote 运行配置。它会自动填充 "Command line arguments for remote JVM",类似于 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005。复制该值,然后打开您想要调试的 IDE。选择 Help -> Edit Custom VM Options,并将复制的行粘贴到打开的文件末尾。重新启动您要调试的 IDE,启动后打开您创建配置的 IDE,并使用您创建的远程配置连接调试器。
有关构建 IDE 插件及其功能的更多信息,请参阅 官方 Jetbrains 文档 或加入 Jetbrains Platform Slack。
驱动程序
如果您有兴趣创建自己的驱动程序,可以使用 runtime 构件在 SQLDelight 仓库之外进行。要测试驱动程序,您可以依赖 driver-test 并扩展 DriverTest 和 TransactionTest,以确保其按 SQLDelight 预期的方式工作。
异步驱动程序
进行异步调用的驱动程序可以使用 runtime-async 构件来实现。
Gradle
如果您遇到 Gradle 问题,请先在 sqldelight-gradle-plugin/src/test 中创建一个类似于该目录下其他文件夹的固定例程,以复现您的问题。如果您不知道如何修复,请随时开启一个包含此失败测试的 拉取请求 (PR)!我们非常欢迎测试用例。集成测试展示了如何设置整个 Gradle 项目,该项目将运行 SQLite/MySQL/PostgreSQL 等,并使用它们各自的运行时环境和 SQLDelight 执行 SQL 查询。如果您在 SQLDelight 中遇到运行时问题,请考虑在这些现有的集成测试中添加测试。
编译器
SQLDelight 的编译器有许多层——如果您只对代码生成(而不是 SQL 的解析)感兴趣,那么您需要在 sqldelight-compiler 模块中进行贡献。如果您对解析器感兴趣,则需要向 sql-psi 贡献代码。SQLDelight 使用 kotlinpoet 来生成 Kotlin 代码,请务必使用其 API 来引用 Kotlin 类型,以便导入仍能正常工作。如果您以任何方式修改了代码生成,请在开启拉取请求 (PR) 之前运行 ./gradlew build,因为它会更新 sqldelight-compiler:integration-tests 中的集成测试。如果您想编写集成测试(即在运行时环境中运行 SQL 查询),请在 sqldelight-compiler:integration-tests 中添加测试。
SQL PSI
在下一节中,我们将介绍如何为解析器和 PSI 层做贡献,但在那之前,您应该阅读一篇关于多个方言的博客文章,以了解 sql-psi 中各种变动的部分。与 SQLDelight 一样,如果您遇到问题但不知道如何贡献修复或需要帮助,请在 GitHub 问题中留言或创建一个新问题以开始讨论。
对于 SQL-PSI 中的任何更改,您都需要在相应的 core/src/test/fixtures_* 文件夹中添加一个固定例程。fixtures 文件夹(无后缀)适用于所有方言。在您的更改合并到 sql-psi 后,如果 SQLDelight 中也需要进行更改,请检出 SQLDelight 上的 sql-psi-dev 分支,并针对该分支提交您的 拉取请求 (PR)。它使用 sql-psi 的快照版本,因此您可以在 sql-psi 的更改合并后大约 10 分钟构建您的 SQLDelight 更改。
语法
如果您正在添加语法,首先要决定这是您添加到现有语法中的新规则,还是您想要从 ANSI SQL(可在 sql.bnf 中找到)中重写的规则。在这两种情况下,您都需要在新语法中定义该规则,但在重写 ANSI SQL 规则的情况下,请将其添加到重写列表并在规则上设置 override 特性:
overrides ::= my_rule
my_rule ::= SOME_TOKEN {
override = true
}您的规则定义应首先精确复制/粘贴 ANSI-SQL 中的规则。要引用 ANSI-SQL 中的规则,您需要将其包裹在 {} 中,因此您应该在重写规则中用 {} 包裹所有外部规则:
my_rule ::= internal_rule {external_rule} {
override = true
}
internal_rule ::= SOME_TOKEN一个注意事项是,引用来自 ANSI-SQL 的 expr 规则时应写为 <<expr '-1'>>,因为它很特殊,无法被重写。
您想从 ANSI SQL 中使用的任何令牌 (token) 也应手动导入:
{
parserImports = [
"static com.alecstrong.sql.psi.core.psi.SqlTypes.DELETE"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.FROM"
]
}
overrides ::= delete
delete ::= DELETE FROM {table_name} {
override = true
}方言不能添加自己的令牌 (token),但您可以通过用 "" 包裹来要求精确的文本:
my_rule ::= "SOME_TOKEN"重写规则必须仍然生成符合原始规则类型的代码,因此请确保为原始规则****实现 (implement) 并扩展 (extend) 现有类型:
my_rule ::= internal_rule {external_rule} {
extends = "com.alecstrong.sql.psi.core.psi.impl.SqlMyRuleImpl"
implements = "com.alecstrong.sql.psi.core.psi.SqlMyRule"
overrides = true
}要查看语法中重写规则的示例,请查看此 PR,它为 PostgreSQL 添加了 RETURNING 语法。
规则行为
通常您希望修改 PSI 层的行为(例如,对于您希望编译失败的情况抛出错误)。为此,请让您的规则使用 mixin(混入)而不是 extends,这是一个包含新逻辑的类:
my_rule ::= interal_rule {external_rule} {
mixin = "com.alecstrong.sql.psi.MyRuleMixin"
implements = "com.alecstrong.sql.psi.core.psi.SqlMyRule"
overrides = true
}然后在该类中确保它实现了原始 ANSI SQL 类型和 SQL-PSI 基类 SqlCompositeElementImpl:
class MyRule(
node: ASTNode
) : SqlCompositeElementImpl(node),
SqlMyRule {
fun annotate(annotationHolder: SqlAnnotationHolder) {
if (internal_rule.text == "bad_text") {
annotationHolder.createErrorAnnotation("Invalid text value", internal_rule)
}
}
}例如,DropIndexMixin 验证了正在删除的索引是否存在于架构中。
如果您有任何关于贡献的问题且本文档未涵盖,请随时在 SqlDelight 上开启一个问题或开启一个 拉取请求 (PR),以便我们改进它!
