Skip to content

贡献

如果您想为本项目贡献代码,可以通过在 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 并扩展 DriverTestTransactionTest,以确保其按 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 特性

bnf
overrides ::= my_rule

my_rule ::= SOME_TOKEN {
  override = true
}

您的规则定义应首先精确复制/粘贴 ANSI-SQL 中的规则。要引用 ANSI-SQL 中的规则,您需要将其包裹在 {} 中,因此您应该在重写规则中用 {} 包裹所有外部规则

bnf
my_rule ::= internal_rule {external_rule} {
  override = true
}
internal_rule ::= SOME_TOKEN

一个注意事项是,引用来自 ANSI-SQL 的 expr 规则时应写为 <<expr '-1'>>,因为它很特殊,无法被重写

您想从 ANSI SQL 中使用的任何令牌 (token) 也应手动导入

bnf
{
  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),但您可以通过用 "" 包裹来要求精确的文本:

bnf
my_rule ::= "SOME_TOKEN"

重写规则必须仍然生成符合原始规则类型的代码,因此请确保为原始规则****实现 (implement) 并扩展 (extend) 现有类型:

bnf
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,这是一个包含新逻辑的类:

bnf
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

kotlin
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),以便我们改进它!