Skip to content

WIP: support language: dart#1146

Open
Lutra-Fs wants to merge 6 commits intoj178:masterfrom
Lutra-Fs:claude/investigate-issue-51-01Canof7ZHmjs9bS4dG4VFbu
Open

WIP: support language: dart#1146
Lutra-Fs wants to merge 6 commits intoj178:masterfrom
Lutra-Fs:claude/investigate-issue-51-01Canof7ZHmjs9bS4dG4VFbu

Conversation

@Lutra-Fs
Copy link
Copy Markdown

Implements full Dart language support following TDD approach:

  • Migrated tests from pre-commit's test suite
  • Implemented Dart language handler in src/languages/dart.rs
    • System Dart installation detection
    • pubspec.yaml dependency installation via dart pub get
    • Additional dependencies via dart pub cache add
    • Environment setup with PUB_CACHE
  • Added comprehensive test suite covering:
    • Health checks
    • Script execution with file arguments
    • pubspec.yaml handling
    • Additional dependencies (with and without versions)
    • Environment variable setup
    • Error handling
  • Updated documentation in docs/todo.md

Language features:

  • Uses system-installed Dart (no version management)
  • Supports additional_dependencies
  • Supports environment setup
  • Compatible with pre-commit Dart hooks

Closes #51

@Lutra-Fs Lutra-Fs changed the title Add Dart language support (#51) WIP: support language: dart Nov 23, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 23, 2025

Codecov Report

❌ Patch coverage is 95.62500% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.18%. Comparing base (0ccaa2e) to head (57435de).

Files with missing lines Patch % Lines
crates/prek/src/languages/dart.rs 95.59% 14 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1146      +/-   ##
==========================================
+ Coverage   92.13%   92.18%   +0.04%     
==========================================
  Files         112      113       +1     
  Lines       23235    23555     +320     
==========================================
+ Hits        21408    21714     +306     
- Misses       1827     1841      +14     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Nov 23, 2025

📦 Cargo Bloat Comparison

Binary size change: +0.00% (25.7 MiB → 25.7 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text     Size             Crate Name
 1.3%   2.6% 332.0KiB        aws_lc_sys aws_lc_0_39_1_aes_gcm_encrypt_avx512
 1.3%   2.6% 332.0KiB        aws_lc_sys aws_lc_0_39_1_aes_gcm_decrypt_avx512
 0.4%   0.7%  92.6KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.7%  85.7KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.6%  71.7KiB             prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.5%  62.9KiB              prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.4%  52.5KiB annotate_snippets annotate_snippets::renderer::render::render
 0.2%   0.4%  46.6KiB              prek prek::run::{{closure}}
 0.2%   0.3%  41.9KiB              prek prek::cli::run::run::run::{{closure}}
 0.1%   0.3%  33.3KiB             prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  30.3KiB             prek? <prek::config::_::<impl serde_core::de::Deserialize for prek::config::Config>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2%  28.0KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_39_1_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_39_1_edwards25519_scalarmuldouble
 0.1%   0.2%  27.5KiB               std core::ptr::drop_in_place<prek::languages::<impl prek::config::Language>::install::{{closure}}>
 0.1%   0.2%  27.1KiB              prek prek::cli::try_repo::try_repo::{{closure}}
 0.1%   0.2%  22.8KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2%  22.6KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2%  22.3KiB         [Unknown] Lp384_montjscalarmul_alt_p384_montjadd
 0.1%   0.2%  21.5KiB      clap_builder clap_builder::parser::parser::Parser::get_matches_with
41.9%  86.2%  10.8MiB                   And 24010 smaller methods. Use -n N to show more.
48.6% 100.0%  12.5MiB                   .text section size, the file size is 25.7MiB

Base Branch Results

 File  .text     Size             Crate Name
 1.3%   2.6% 332.0KiB        aws_lc_sys aws_lc_0_39_1_aes_gcm_encrypt_avx512
 1.3%   2.6% 332.0KiB        aws_lc_sys aws_lc_0_39_1_aes_gcm_decrypt_avx512
 0.3%   0.7%  88.1KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.6%  82.1KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.6%  72.0KiB             prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.4%  57.0KiB              prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.4%  52.5KiB annotate_snippets annotate_snippets::renderer::render::render
 0.2%   0.4%  46.6KiB              prek prek::run::{{closure}}
 0.2%   0.3%  42.0KiB              prek prek::cli::run::run::run::{{closure}}
 0.1%   0.3%  32.6KiB             prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  30.0KiB             prek? <prek::config::_::<impl serde_core::de::Deserialize for prek::config::Config>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2%  28.0KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_39_1_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_39_1_edwards25519_scalarmuldouble
 0.1%   0.2%  27.1KiB              prek prek::cli::try_repo::try_repo::{{closure}}
 0.1%   0.2%  26.8KiB               std core::ptr::drop_in_place<prek::languages::<impl prek::config::Language>::install::{{closure}}>
 0.1%   0.2%  22.8KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2%  22.6KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2%  22.3KiB         [Unknown] Lp384_montjscalarmul_alt_p384_montjadd
 0.1%   0.2%  21.5KiB      clap_builder clap_builder::parser::parser::Parser::get_matches_with
41.8%  86.3%  10.8MiB                   And 24081 smaller methods. Use -n N to show more.
48.5% 100.0%  12.5MiB                   .text section size, the file size is 25.7MiB

@Lutra-Fs
Copy link
Copy Markdown
Author

Still early WIP-haven't checked the parts around the missing test yet. I'd like to try this out with my Flutter repo so that's why I start this PR. Also, I'm using Claude code on web (which is providing credits until tomorrow) for much of the implementation. Plan to do a deeper cleanup and address more details tomorrow. Let me know if you have any early feedback or suggestions!

@Lutra-Fs
Copy link
Copy Markdown
Author

I came across this repo thanks to the PR to Scoop. It's a great project, and I hope to contribute some features or fixes as I get more familiar with it!

@j178
Copy link
Copy Markdown
Owner

j178 commented Nov 23, 2025

Thank you! The code looks good to me. However, since I'm not very familiar with the Dart ecosystem, I'll need a bit more time to review the details and make sure everything works as expected.

@Lutra-Fs Lutra-Fs force-pushed the claude/investigate-issue-51-01Canof7ZHmjs9bS4dG4VFbu branch from 0264c93 to 9d1e1ec Compare April 16, 2026 06:01
@prek-ci-bot
Copy link
Copy Markdown

prek-ci-bot Bot commented Apr 16, 2026

⚡️ Hyperfine Benchmarks

Summary: 0 regressions, 0 improvements above the 10% threshold.

Environment
  • OS: Linux 6.17.0-1010-azure
  • CPU: 4 cores
  • prek version: prek 0.3.9+14 (c86d2ba 2026-04-18)
  • Rust version: rustc 1.94.1 (e408947bf 2026-03-25)
  • Hyperfine version: hyperfine 1.20.0
CLI Commands

Benchmarking basic commands in the main repo:

prek --version

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base --version 2.2 ± 0.1 2.0 2.8 1.01 ± 0.06
prek-head --version 2.2 ± 0.1 2.0 2.6 1.00

prek list

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base list 8.6 ± 0.2 8.4 10.1 1.00
prek-head list 8.7 ± 0.2 8.4 9.7 1.01 ± 0.04

prek validate-config .pre-commit-config.yaml

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base validate-config .pre-commit-config.yaml 2.9 ± 0.0 2.8 3.0 1.00
prek-head validate-config .pre-commit-config.yaml 2.9 ± 0.1 2.8 3.5 1.01 ± 0.04

prek sample-config

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base sample-config 2.4 ± 0.0 2.3 2.5 1.00
prek-head sample-config 2.4 ± 0.0 2.3 2.5 1.01 ± 0.02
Cold vs Warm Runs

Comparing first run (cold) vs subsequent runs (warm cache):

prek run --all-files (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 142.4 ± 2.4 138.4 145.3 1.00
prek-head run --all-files 144.9 ± 3.5 138.2 149.8 1.02 ± 0.03

prek run --all-files (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 140.8 ± 2.9 135.5 146.7 1.00
prek-head run --all-files 140.9 ± 3.1 135.5 146.8 1.00 ± 0.03
Full Hook Suite

Running the builtin hook suite on the benchmark workspace:

prek run --all-files (full builtin hook suite)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 141.8 ± 3.7 134.7 151.7 1.00
prek-head run --all-files 142.2 ± 3.7 135.7 150.0 1.00 ± 0.04
Individual Hook Performance

Benchmarking each hook individually on the test repo:

prek run trailing-whitespace --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run trailing-whitespace --all-files 19.9 ± 0.4 19.2 20.7 1.00
prek-head run trailing-whitespace --all-files 25.5 ± 19.5 19.5 125.5 1.28 ± 0.98

prek run end-of-file-fixer --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run end-of-file-fixer --all-files 26.9 ± 2.3 23.2 30.6 1.02 ± 0.12
prek-head run end-of-file-fixer --all-files 26.3 ± 2.2 23.1 30.5 1.00

prek run check-json --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-json --all-files 11.0 ± 0.2 10.6 11.6 1.01 ± 0.03
prek-head run check-json --all-files 10.9 ± 0.2 10.5 11.4 1.00

prek run check-yaml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-yaml --all-files 10.8 ± 0.2 10.5 11.5 1.00 ± 0.03
prek-head run check-yaml --all-files 10.8 ± 0.2 10.5 11.3 1.00

prek run check-toml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-toml --all-files 10.9 ± 0.3 10.5 11.9 1.00 ± 0.04
prek-head run check-toml --all-files 10.9 ± 0.2 10.6 11.6 1.00

prek run check-xml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-xml --all-files 11.3 ± 0.2 10.9 11.7 1.01 ± 0.03
prek-head run check-xml --all-files 11.2 ± 0.3 10.7 11.8 1.00

prek run detect-private-key --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run detect-private-key --all-files 17.4 ± 1.4 15.4 20.3 1.04 ± 0.11
prek-head run detect-private-key --all-files 16.8 ± 1.1 14.6 20.0 1.00

prek run fix-byte-order-marker --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run fix-byte-order-marker --all-files 21.8 ± 1.5 19.2 24.2 1.00 ± 0.11
prek-head run fix-byte-order-marker --all-files 21.7 ± 1.9 18.9 26.5 1.00
Installation Performance

Benchmarking hook installation (fast path hooks skip Python setup):

prek install-hooks (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 4.6 ± 0.1 4.5 4.8 1.06 ± 0.03
prek-head install-hooks 4.4 ± 0.1 4.3 4.4 1.00

prek install-hooks (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 4.3 ± 0.0 4.3 4.4 1.00
prek-head install-hooks 4.4 ± 0.0 4.3 4.4 1.01 ± 0.01
File Filtering/Scoping Performance

Testing different file selection modes:

prek run (staged files only)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run 48.2 ± 0.8 47.0 49.5 1.00
prek-head run 48.9 ± 1.1 47.2 51.0 1.01 ± 0.03

prek run --files '*.json' (specific file type)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --files '*.json' 8.3 ± 0.2 8.0 8.6 1.03 ± 0.02
prek-head run --files '*.json' 8.1 ± 0.1 7.9 8.2 1.00
Workspace Discovery & Initialization

Benchmarking hook discovery and initialization overhead:

prek run --dry-run --all-files (measures init overhead)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --dry-run --all-files 12.5 ± 0.4 12.2 14.1 1.01 ± 0.03
prek-head run --dry-run --all-files 12.4 ± 0.1 12.2 12.6 1.00
Meta Hooks Performance

Benchmarking meta hooks separately:

prek run check-hooks-apply --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-hooks-apply --all-files 12.6 ± 0.1 12.5 12.7 1.00
prek-head run check-hooks-apply --all-files 12.7 ± 0.1 12.5 13.0 1.00 ± 0.01

prek run check-useless-excludes --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-useless-excludes --all-files 12.5 ± 0.1 12.3 12.7 1.11 ± 0.03
prek-head run check-useless-excludes --all-files 11.2 ± 0.3 11.0 12.4 1.00

prek run identity --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run identity --all-files 9.7 ± 0.1 9.6 9.9 1.00
prek-head run identity --all-files 9.8 ± 0.1 9.5 9.9 1.00 ± 0.01

@Lutra-Fs Lutra-Fs marked this pull request as ready for review April 17, 2026 11:48
@Lutra-Fs Lutra-Fs requested a review from j178 as a code owner April 17, 2026 11:48
Copilot AI review requested due to automatic review settings April 17, 2026 11:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds initial support for language: dart to prek by introducing a Dart language implementation and an accompanying integration test suite, plus CI wiring to exercise those tests.

Changes:

  • Added a new Dart language handler (crates/prek/src/languages/dart.rs) and wired it into the language dispatcher.
  • Added comprehensive Dart language integration tests and nextest profile support.
  • Updated CI to install Dart and run Dart language tests; added snapshot filtering for Dart version output.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/prek/tests/languages/main.rs Registers the new dart test module.
crates/prek/tests/languages/dart.rs Adds Dart language integration tests (health, deps, pubspec behavior, env vars, remote hook).
crates/prek/tests/common/mod.rs Adds an insta filter to normalize Dart SDK version output in snapshots.
crates/prek/src/languages/mod.rs Wires Language::Dart into install/health/run dispatch and marks it supported.
crates/prek/src/languages/dart.rs Implements Dart install/health/run logic (system dart, pubspec/env pubspec, dart pub get, executable compilation).
crates/prek-consts/src/env_vars.rs Adds PUB_CACHE env var constant.
.github/workflows/ci.yml Installs Dart in the language test matrix and adds dart to the matrix.
.config/nextest.toml Adds a lang-dart nextest profile to run only Dart language tests.

Comment on lines +45 to +60
let stdout = Cmd::new(&executable, "get dart version")
.arg("--version")
.check(true)
.output()
.await?
.stdout;

let version = str::from_utf8(&stdout)
.context("Failed to parse `dart --version` output as UTF-8")?
.lines()
.find(|line| line.contains("Dart SDK version:"))
.and_then(|line| line.split_whitespace().nth(3))
.context("Failed to extract Dart version from output")?
.trim();
let version = Version::parse(version).context("Failed to parse Dart version")?;

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query_dart_info() only parses stdout from dart --version, but many Dart installations print the version string to stderr (similar to java -version). This can make Dart support fail at install/health-check time even though dart is present. Consider parsing from both streams (e.g., combine stdout + stderr, or fall back to stderr when stdout is empty).

Copilot uses AI. Check for mistakes.
Comment on lines +391 to +405
let pubspec_content = Self::build_env_pubspec(source_path, package_name, dependencies)?;
let pubspec_path = env_path.join("pubspec.yaml");
fs_err::tokio::write(&pubspec_path, pubspec_content).await?;

Cmd::new(dart, "dart pub get")
.current_dir(env_path)
.env(EnvVars::PUB_CACHE, env_path)
.arg("pub")
.arg("get")
.check(true)
.output()
.await
.context("Failed to run dart pub get")?;

Ok(())
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description mentions installing additional_dependencies via dart pub cache add, but the implementation installs them by generating a pubspec and running dart pub get. Either update the PR description to match the implementation, or switch the code to the intended dart pub cache add flow if that’s required for compatibility with pre-commit’s Dart language behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +595 to +609
#[test]
// Temporarily hosted under Lutra-Fs until upstream fixture repo access is available.
fn remote_hook() {
let context = TestContext::new();
context.init_project();

context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: https://github.com/Lutra-Fs/dart-hooks
rev: v1.1.0
hooks:
- id: dart-hooks
always_run: true
verbose: true
"});
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remote_hook test depends on a third-party repo (Lutra-Fs/dart-hooks) rather than the existing prek-test-repos/* fixtures used by other language tests. This increases CI flakiness/risk (repo rename/deletion, rate limits, etc.). Consider moving the fixture under the project’s standard test-fixture org or vendoring a minimal test repo, or gating/ignoring this test when the fixture isn’t guaranteed available.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6eeb4fe47

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +442 to +444
Self::install_package_config(dart, env_path, None, None, dependencies)
.await
.context("Failed to run dart pub get for additional dependencies")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Build binaries for additional Dart deps

This path installs additional_dependencies only via dart pub get and then returns, so no executable is produced in env/bin. In run(), hook entries are resolved from PATH with env/bin prepended, so configurations like entry: some_cli + additional_dependencies: ['some_cli:1.2.3'] will still fail with command-not-found even though dependency installation succeeded. This breaks the common Dart-hook expectation that dependency-provided executables can be invoked as the hook entry.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dart language

3 participants