Skip to content

貢獻

如果您想為此專案貢獻程式碼,可以透過 GitHub 分支 (fork) 存儲庫並發送提取要求 (pull request)。

提交程式碼時,請盡力遵循現有的慣例與風格,以保持程式碼盡可能具備可讀性。

在您的程式碼被專案接受之前,您還必須簽署 個人貢獻者授權協議 (Individual Contributor License Agreement, CLA)

SQLDelight

如果您正想開始嘗試貢獻,請根據您想貢獻的 SQLDelight 部分參閱下方的特定指南。如果您仍不確定,請在您關注的問題 (issue) 中留言說明您卡住的地方,我們會在該處回覆,或者為您想做的事情建立一個問題並開始討論。

IDE 外掛程式 (Plugin)

如果您想修復錯誤 (bug) 或擴充 IDE,程式碼變更通常會發生在 sqldelight-idea-plugin 模組中。您可以使用 ./gradlew runIde 任務來測試您的變更,並可以使用 ./gradlew runIde --debug-jvm 進行即時偵錯。

如果您在 IDE 中遇到錯誤,但無法在範例專案中重現,您可以對您的 IDE 進行即時偵錯。您需要安裝第二個 IntelliJ 才能執行此操作。您可以使用 Toolbox,捲動到 IDE 列表底部並選擇不同版本的 IntelliJ 來達成此目的。

在您想使用偵錯工具的 IDE 中,檢出 SQLDelight 存儲庫,然後建立一個新的 Remote 執行配置 (Run Configuration)。它會自動填入「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

驅動程式 (Drivers)

如果您有興趣建立自己的驅動程式,可以使用 runtime 構件 (artifact) 在 SQLDelight 存儲庫之外進行。若要測試驅動程式,您可以相依於 driver-test 並擴充 DriverTestTransactionTest,以確保其運作符合 SQLDelight 的預期。

非同步驅動程式

發送非同步呼叫的驅動程式可以透過使用 runtime-async 構件來實作。

Gradle

如果您遇到 Gradle 問題,請先在 sqldelight-gradle-plugin/src/test 中建立一個與該處其他資料夾類似的測試夾具 (test fixture) 來重現您的問題。如果您不知道如何修復,歡迎直接開啟一個帶有此失敗測試的提取要求 (PR)!我們非常歡迎提供測試案例。整合測試展示了如何設定整個 Gradle 專案,該專案將執行 SQLite/MySQL/PostgreSQL 等,並使用各自的執行環境與 SQLDelight 執行 SQL 查詢。如果您在 SQLDelight 中遇到執行期問題,請考慮將測試加入這些已有的整合測試中。

編譯器 (Compiler)

SQLDelight 的編譯器有多個層級——如果您僅對程式碼產生 (codegen) 感興趣(而非 SQL 的剖析),那麼您會希望在 sqldelight-compiler 模組中進行貢獻。如果您對剖析器 (parser) 感興趣,則需要貢獻至 sql-psi。SQLDelight 使用 kotlinpoet 來產生 Kotlin 程式碼,請務必使用其 API 來參照 Kotlin 型別,以便匯入仍能正確運作。如果您以任何方式修改了程式碼產生,請在開啟提取要求之前執行 ./gradlew build,因為它會更新 sqldelight-compiler:integration-tests 中的整合測試。如果您想撰寫整合測試(意即在執行環境中執行 SQL 查詢),請將測試加入 sqldelight-compiler:integration-tests


SQL PSI

在下一節中,我們將介紹如何貢獻至剖析器與 PSI 層,但在執行此操作之前,您應該閱讀一篇關於 多種方言 (multiple dialects) 的部落格文章,以了解 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 變更。

語法 (Grammar)

如果您要增加語法,首先要決定這是您要加入現有語法的新規則,還是您想要從 ANSI SQL 覆寫的規則(ANSI SQL 位於 sql.bnf)。在這兩種情況下,您都需要在新的語法中定義該規則,但在覆寫 ANSI SQL 規則的情況下,請將其加入 overrides 列表並在規則上設定覆寫屬性:

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
}

方言不能加入自己的標記,但您可以透過用 "" 包圍來要求確切的文字:

bnf
my_rule ::= "SOME_TOKEN"

覆寫規則仍必須產生符合原始規則型別的程式碼,因此請務必為原始規則 implementextend 現有型別:

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,該 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

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 會驗證正在刪除的索引是否存在於結構 (schema) 中。


如果您對本文件未涵蓋的貢獻有任何疑問,請隨時在 SqlDelight 上建立問題或開啟 PR,以便我們改進!