diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml new file mode 100644 index 00000000..c55bf403 --- /dev/null +++ b/.github/actions/free-disk-space/action.yml @@ -0,0 +1,16 @@ +name: Free Disk Space +description: Free up disk space on the runner +runs: + using: composite + steps: + - name: Free Disk Space (Ubuntu) + if: runner.os == 'Linux' + uses: jlumbroso/free-disk-space@main + with: + # We need to reclaim some space, but uninstalling everyting takes + # too long. So we'll just remove some of the larger packages. + # https://github.com/jlumbroso/free-disk-space/pull/26 + android: true + dotnet: true + haskell: true + large-packages: false diff --git a/.github/actions/setup-monorepo/action.yml b/.github/actions/setup-monorepo/action.yml deleted file mode 100644 index c697b3d8..00000000 --- a/.github/actions/setup-monorepo/action.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Setup Monorepo -description: Prepare and install everything for the monorepo - -inputs: - github-token: - description: The GitHub token - - toolchain: - description: Toolchain name to use - default: nightly - -runs: - using: composite - steps: - - name: 🏗 Setup Toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ inputs.toolchain }} - - - name: 🔒 Cache - uses: swatinem/rust-cache@v2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 691d6716..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: CI - -on: - workflow_dispatch: - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true - -env: - RUSTFLAGS: --deny warnings - -jobs: - ci: - name: CI - timeout-minutes: 10 - runs-on: ubuntu-latest - - services: - postgres: - image: postgres:latest - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: postgres - ports: - - 5432:5432 - - env: - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres - - steps: - - name: 🏗 Setup repository - uses: actions/checkout@v3 - with: - submodules: true - - - name: 🏗 Setup monorepo - uses: ./.github/actions/setup-monorepo - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Run test migrations - run: psql -f test-db/seed.sql postgresql://postgres:postgres@localhost:5432/postgres - - - name: 📦 Build - id: build - run: RUSTFLAGS="-A dead_code" cargo build - - - name: ⚡️ Check - id: check - run: RUSTFLAGS="-A dead_code" cargo check - - - name: 🦺 Test - id: test - run: RUSTFLAGS="-A dead_code" cargo test diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..b75489f7 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,183 @@ +name: Pull Request + +on: + workflow_dispatch: + pull_request: + paths: # Only run when changes are made to rust code or root Cargo + - "crates/**" + - "lib/**" + - "fuzz/**" + - "xtask/**" + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain.toml" + - "rustfmt.toml" + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +env: + RUSTFLAGS: -A dead_code + RUST_LOG: info + RUST_BACKTRACE: 1 + RUSTUP_WINDOWS_PATH_ADD_BIN: 1 + +jobs: + format: + name: Format + runs-on: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + - name: Install toolchain + uses: moonrepo/setup-rust@v1 + with: + components: rustfmt + bins: taplo-cli + cache-base: main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run format + run: | + cargo fmt --all --check + taplo format --check + + actionlint: + name: Lint GitHub Actions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download actionlint + id: get_actionlint + run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + shell: bash + - name: Check workflow files + run: ${{ steps.get_actionlint.outputs.executable }} -color + shell: bash + + lint: + name: Lint Project + runs-on: ubuntu-latest + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + steps: + - name: Checkout PR Branch + uses: actions/checkout@v4 + with: + submodules: true + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + - name: Install toolchain + uses: moonrepo/setup-rust@v1 + with: + components: clippy + cache-base: main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run clippy + run: | + cargo clippy + cargo run -p rules_check + + # check-dependencies: + # name: Check Dependencies + # runs-on: ubuntu-latest + # services: + # postgres: + # image: postgres:latest + # env: + # POSTGRES_USER: postgres + # POSTGRES_PASSWORD: postgres + # POSTGRES_DB: postgres + # ports: + # - 5432:5432 + # steps: + # - name: Checkout PR Branch + # uses: actions/checkout@v4 + # with: + # submodules: true + # - name: Free Disk Space + # uses: ./.github/actions/free-disk-space + # - name: Install toolchain + # run: rustup toolchain install nightly + # - name: Install udeps + # run: cargo install cargo-udeps --locked + # - name: Detect unused dependencies using udeps + # run: cargo +nightly udeps --all-targets + + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + # reactive once we upgrade to the latest version of pg_query that is windows-compatible + # - os: windows-latest + - os: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + submodules: true + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + - name: Install toolchain + uses: moonrepo/setup-rust@v1 + with: + cache-base: main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # running containers via `services` only works on linux + # https://github.com/actions/runner/issues/1866 + - name: Setup postgres + uses: ikalnytskyi/action-setup-postgres@v7 + - name: Run tests + run: cargo test --workspace + + codegen: + name: Check Codegen + runs-on: ubuntu-latest + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + submodules: true + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + - name: Install toolchain + uses: moonrepo/setup-rust@v1 + with: + cache-base: main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run the analyser codegen + run: cargo run -p xtask_codegen -- analyser + - name: Run the configuration codegen + run: cargo run -p xtask_codegen -- configuration + - name: Check for git diff + run: | + if [[ $(git status --porcelain) ]]; then + git status + git diff + exit 1 + fi diff --git a/crates/pg_completions/src/context.rs b/crates/pg_completions/src/context.rs index 79354cf6..912a7cec 100644 --- a/crates/pg_completions/src/context.rs +++ b/crates/pg_completions/src/context.rs @@ -29,7 +29,7 @@ impl TryFrom<&str> for ClauseType { panic!("{}", message); } - return Err(message); + Err(message) } } } @@ -215,7 +215,7 @@ mod tests { let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; @@ -247,7 +247,7 @@ mod tests { let tree = get_tree(text.as_str()); let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; @@ -281,7 +281,7 @@ mod tests { let tree = get_tree(text.as_str()); let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; @@ -306,14 +306,14 @@ mod tests { let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; let ctx = CompletionContext::new(¶ms); - let node = ctx.ts_node.map(|n| n.clone()).unwrap(); + let node = ctx.ts_node.unwrap(); assert_eq!(ctx.get_ts_node_content(node), Some("select")); @@ -334,14 +334,14 @@ mod tests { let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; let ctx = CompletionContext::new(¶ms); - let node = ctx.ts_node.map(|n| n.clone()).unwrap(); + let node = ctx.ts_node.unwrap(); assert_eq!(ctx.get_ts_node_content(node), Some("from")); assert_eq!( @@ -360,14 +360,14 @@ mod tests { let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; let ctx = CompletionContext::new(¶ms); - let node = ctx.ts_node.map(|n| n.clone()).unwrap(); + let node = ctx.ts_node.unwrap(); assert_eq!(ctx.get_ts_node_content(node), Some("")); assert_eq!(ctx.wrapping_clause_type, None); @@ -385,14 +385,14 @@ mod tests { let params = crate::CompletionParams { position: (position as u32).into(), - text: text, + text, tree: Some(&tree), schema: &pg_schema_cache::SchemaCache::new(), }; let ctx = CompletionContext::new(¶ms); - let node = ctx.ts_node.map(|n| n.clone()).unwrap(); + let node = ctx.ts_node.unwrap(); assert_eq!(ctx.get_ts_node_content(node), Some("fro")); assert_eq!(ctx.wrapping_clause_type, Some(ClauseType::Select)); diff --git a/crates/pg_completions/src/test_helper.rs b/crates/pg_completions/src/test_helper.rs index 08a3af2e..4c29d1e7 100644 --- a/crates/pg_completions/src/test_helper.rs +++ b/crates/pg_completions/src/test_helper.rs @@ -34,10 +34,9 @@ pub(crate) async fn get_test_deps( pub(crate) fn get_text_and_position(sql: &str) -> (usize, String) { // the cursor is to the left of the `CURSOR_POS` let position = sql - .find(|c| c == CURSOR_POS) + .find(CURSOR_POS) .expect("Please insert the CURSOR_POS into your query.") - .checked_sub(1) - .unwrap_or(0); + .saturating_sub(1); let text = sql.replace(CURSOR_POS, ""); diff --git a/crates/pg_console/src/utils.rs b/crates/pg_console/src/utils.rs index 6524b3da..d56e0139 100644 --- a/crates/pg_console/src/utils.rs +++ b/crates/pg_console/src/utils.rs @@ -3,7 +3,6 @@ use crate::{markup, Markup}; use std::io; /// It displays a type that implements [std::fmt::Display] - pub struct DebugDisplay(pub T); impl Display for DebugDisplay diff --git a/crates/pg_diagnostics/src/display/backtrace.rs b/crates/pg_diagnostics/src/display/backtrace.rs index c5ba1a1e..bae7d979 100644 --- a/crates/pg_diagnostics/src/display/backtrace.rs +++ b/crates/pg_diagnostics/src/display/backtrace.rs @@ -148,7 +148,7 @@ impl NativeBacktrace { frame.symbols().iter().any(|symbol| { symbol .addr() - .map_or(false, |addr| addr as usize == self.top_frame) + .is_some_and(|addr| addr as usize == self.top_frame) }) }); @@ -162,7 +162,7 @@ impl NativeBacktrace { frame.symbols().iter().any(|symbol| { symbol .addr() - .map_or(false, |addr| addr as usize == self.bottom_frame) + .is_some_and(|addr| addr as usize == self.bottom_frame) }) }); diff --git a/crates/pg_diagnostics/src/display/frame.rs b/crates/pg_diagnostics/src/display/frame.rs index 8013148e..8719cc0d 100644 --- a/crates/pg_diagnostics/src/display/frame.rs +++ b/crates/pg_diagnostics/src/display/frame.rs @@ -411,7 +411,7 @@ pub(super) fn print_invisibles( let next_char_is_whitespace = iter .peek() - .map_or(false, |(_, char)| char.is_ascii_whitespace()); + .is_some_and(|(_, char)| char.is_ascii_whitespace()); if prev_char_was_whitespace || next_char_is_whitespace { show_invisible = false; @@ -436,7 +436,7 @@ pub(super) fn print_invisibles( // If we are a carriage return next to a \n then don't show the character as visible if options.ignore_trailing_carriage_return && char == '\r' { - let next_char_is_line_feed = iter.peek().map_or(false, |(_, char)| *char == '\n'); + let next_char_is_line_feed = iter.peek().is_some_and(|(_, char)| *char == '\n'); if next_char_is_line_feed { continue; } diff --git a/crates/pg_lsp/src/db_connection.rs b/crates/pg_lsp/src/db_connection.rs index 38286ea5..4e0bdb72 100644 --- a/crates/pg_lsp/src/db_connection.rs +++ b/crates/pg_lsp/src/db_connection.rs @@ -40,7 +40,7 @@ impl DbConnection { res = listener.recv() => { match res { Ok(not) => { - if not.payload().to_string() == "reload schema" { + if not.payload() == "reload schema" { let schema_cache = SchemaCache::load(&cloned_pool).await.unwrap(); ide.write().await.set_schema_cache(schema_cache); }; diff --git a/crates/pg_lsp/src/session.rs b/crates/pg_lsp/src/session.rs index 4e4dcfd9..16d99459 100644 --- a/crates/pg_lsp/src/session.rs +++ b/crates/pg_lsp/src/session.rs @@ -245,11 +245,7 @@ impl Session { let completion_items: Vec = pg_completions::complete(CompletionParams { position: offset - range.start() - TextSize::from(1), text: stmt.text.clone(), - tree: ide - .tree_sitter - .tree(&stmt) - .as_ref() - .and_then(|t| Some(t.as_ref())), + tree: ide.tree_sitter.tree(&stmt).as_ref().map(|t| t.as_ref()), schema: &schema_cache, }) .into_iter() diff --git a/crates/pg_schema_cache/src/columns.rs b/crates/pg_schema_cache/src/columns.rs index 1ff4a412..a8d88eae 100644 --- a/crates/pg_schema_cache/src/columns.rs +++ b/crates/pg_schema_cache/src/columns.rs @@ -148,27 +148,27 @@ mod tests { user_id_col.default_expr, Some("nextval('users_id_seq'::regclass)".into()) ); - assert_eq!(user_id_col.is_nullable, false); - assert_eq!(user_id_col.is_primary_key, true); - assert_eq!(user_id_col.is_unique, true); + assert!(!user_id_col.is_nullable); + assert!(user_id_col.is_primary_key); + assert!(user_id_col.is_unique); assert_eq!(user_id_col.varchar_length, None); let user_name_col = cache.find_col("name", "users", None).unwrap(); assert_eq!(user_name_col.class_kind, ColumnClassKind::OrdinaryTable); assert_eq!(user_name_col.comment, None); assert_eq!(user_name_col.default_expr, None); - assert_eq!(user_name_col.is_nullable, false); - assert_eq!(user_name_col.is_primary_key, false); - assert_eq!(user_name_col.is_unique, false); + assert!(!user_name_col.is_nullable); + assert!(!user_name_col.is_primary_key); + assert!(!user_name_col.is_unique); assert_eq!(user_name_col.varchar_length, Some(255)); let user_is_veg_col = cache.find_col("is_vegetarian", "users", None).unwrap(); assert_eq!(user_is_veg_col.class_kind, ColumnClassKind::OrdinaryTable); assert_eq!(user_is_veg_col.comment, None); assert_eq!(user_is_veg_col.default_expr, Some("false".into())); - assert_eq!(user_is_veg_col.is_nullable, true); - assert_eq!(user_is_veg_col.is_primary_key, false); - assert_eq!(user_is_veg_col.is_unique, false); + assert!(user_is_veg_col.is_nullable); + assert!(!user_is_veg_col.is_primary_key); + assert!(!user_is_veg_col.is_unique); assert_eq!(user_is_veg_col.varchar_length, None); let user_middle_name_col = cache.find_col("middle_name", "users", None).unwrap(); @@ -178,9 +178,9 @@ mod tests { ); assert_eq!(user_middle_name_col.comment, None); assert_eq!(user_middle_name_col.default_expr, None); - assert_eq!(user_middle_name_col.is_nullable, true); - assert_eq!(user_middle_name_col.is_primary_key, false); - assert_eq!(user_middle_name_col.is_unique, false); + assert!(user_middle_name_col.is_nullable); + assert!(!user_middle_name_col.is_primary_key); + assert!(!user_middle_name_col.is_unique); assert_eq!(user_middle_name_col.varchar_length, Some(255)); let properties_owner_id_col = cache @@ -194,9 +194,9 @@ mod tests { properties_owner_id_col.comment, Some("users might own many houses".into()) ); - assert_eq!(properties_owner_id_col.is_nullable, true); - assert_eq!(properties_owner_id_col.is_primary_key, false); - assert_eq!(properties_owner_id_col.is_unique, false); + assert!(properties_owner_id_col.is_nullable); + assert!(!properties_owner_id_col.is_primary_key); + assert!(!properties_owner_id_col.is_unique); assert_eq!(properties_owner_id_col.varchar_length, None); } } diff --git a/crates/pg_schema_cache/src/schema_cache.rs b/crates/pg_schema_cache/src/schema_cache.rs index 6deac6f1..8d73e631 100644 --- a/crates/pg_schema_cache/src/schema_cache.rs +++ b/crates/pg_schema_cache/src/schema_cache.rs @@ -66,7 +66,7 @@ impl SchemaCache { self.columns.iter().find(|c| { c.name.as_str() == name && c.table_name.as_str() == table - && schema.map_or(true, |s| s == c.schema_name.as_str()) + && schema.is_none_or(|s| s == c.schema_name.as_str()) }) } diff --git a/crates/pg_workspace_new/src/workspace/server/pg_query.rs b/crates/pg_workspace_new/src/workspace/server/pg_query.rs index e14e0a27..cbdf8bf0 100644 --- a/crates/pg_workspace_new/src/workspace/server/pg_query.rs +++ b/crates/pg_workspace_new/src/workspace/server/pg_query.rs @@ -1,9 +1,8 @@ use std::sync::Arc; use dashmap::DashMap; -use pg_diagnostics::{serde::Diagnostic as SDiagnostic, Diagnostic, MessageAndDescription}; +use pg_diagnostics::serde::Diagnostic as SDiagnostic; use pg_query_ext::diagnostics::*; -use text_size::TextRange; use super::{ change::ChangedStatement, diff --git a/justfile b/justfile index 3cd149ad..aafa199f 100644 --- a/justfile +++ b/justfile @@ -104,9 +104,11 @@ test-doc: # Alias for `cargo clippy`, it runs clippy on the whole codebase lint: cargo clippy + cargo run -p rules_check lint-fix: cargo clippy --fix + cargo run -p rules_check # When you finished coding, run this command to run the same commands in the CI. # ready: @@ -140,7 +142,10 @@ clear-branches: git branch --merged | egrep -v "(^\\*|main)" | xargs git branch -d reset-git: - git checkout main && git pull && pnpm run clear-branches + git checkout main + git pull + just clear-branches merge-main: - git fetch origin main:main && git merge main + git fetch origin main:main + git merge main