From 0acdb0d047724063ceb774c91391481a3e64b8aa Mon Sep 17 00:00:00 2001 From: Niklas Zender Date: Wed, 24 Jun 2026 15:14:13 +0200 Subject: [PATCH 1/2] feat(dart): Distribute shared analyzer configuration For every configured Dart project, place a managed `analysis_options.standards.yaml` (always overwritten) and an initial, repo-owned `analysis_options.yaml` that includes it, via filegen. This gives the IDE analyzer, `dart analyze`, and the CI `dart_code_linter` step a single shared source of truth for lint rules. The template files live under `standards/dart/`, matching the existing `standards/` convention for repo-owned data consumed by the Nix modules. Co-authored-by: Cursor --- nix/dart/default.nix | 1 + nix/dart/linting.nix | 42 ++++++++++++ .../dart/analysis_options.standards.yaml | 66 +++++++++++++++++++ standards/dart/analysis_options.yaml | 14 ++++ 4 files changed, 123 insertions(+) create mode 100644 nix/dart/linting.nix create mode 100644 standards/dart/analysis_options.standards.yaml create mode 100644 standards/dart/analysis_options.yaml diff --git a/nix/dart/default.nix b/nix/dart/default.nix index 0d005af..2d28cd8 100644 --- a/nix/dart/default.nix +++ b/nix/dart/default.nix @@ -7,6 +7,7 @@ importingFlake: { imports = [ (importApply ./devshell.nix args) + (importApply ./linting.nix args) (importApply ./sdk.nix args) ./workflow.nix ]; diff --git a/nix/dart/linting.nix b/nix/dart/linting.nix new file mode 100644 index 0000000..3c95ee4 --- /dev/null +++ b/nix/dart/linting.nix @@ -0,0 +1,42 @@ +# Dart linting configuration. +# +# For every configured Dart project, place the shared analyzer configuration +# via filegen: +# +# analysis_options.standards.yaml — managed, always overwritten +# analysis_options.yaml — created once, then owned by the repo +# +# The standards file drives `dart analyze`, the IDE analyzer, and the +# `dart_code_linter` step of the Dart CI workflow, so local and CI analysis +# share one source of truth. +{ ... }: +importingFlake: { + perSystem = + { config, lib, ... }: + let + projects = config.famedly.standards.dart.projects; + + mkProjectFiles = + name: _: + let + dir = if name == "." then "" else "${lib.removePrefix "./" name}/"; + in + [ + { + type = "copy"; + target = "./${dir}analysis_options.standards.yaml"; + source = ../../standards/dart/analysis_options.standards.yaml; + clobber = true; + } + { + type = "copy"; + target = "./${dir}analysis_options.yaml"; + source = ../../standards/dart/analysis_options.yaml; + clobber = false; + } + ]; + in + lib.mkIf (projects != { }) { + filegen.settings.files = lib.concatLists (lib.mapAttrsToList mkProjectFiles projects); + }; +} diff --git a/standards/dart/analysis_options.standards.yaml b/standards/dart/analysis_options.standards.yaml new file mode 100644 index 0000000..3157231 --- /dev/null +++ b/standards/dart/analysis_options.standards.yaml @@ -0,0 +1,66 @@ +# managed-by: engineering-standards — do not edit manually. +# +# This file is placed by the engineering-standards flake. Regenerate it with: +# nix run .#filegen-activate +# +# Put repo-specific overrides in analysis_options.yaml (which includes this +# file), never here. Using these rules requires the following dev_dependencies: +# dev_dependencies: +# lints: ^6.0.0 +# dart_code_linter: ^3.2.1 +include: package:lints/recommended.yaml + +linter: + rules: + - avoid_print + - constant_identifier_names + - prefer_final_locals + - prefer_final_in_for_each + - sort_pub_dependencies + - require_trailing_commas + - omit_local_variable_types + - cancel_subscriptions + - always_declare_return_types + - avoid_void_async + - no_adjacent_strings_in_list + - test_types_in_equals + - throw_in_finally + - unnecessary_statements + - avoid_bool_literals_in_conditional_expressions + - prefer_single_quotes + - prefer_const_declarations + - unnecessary_lambdas + - combinators_ordering + - noop_primitive_operations + - unnecessary_null_checks + - unnecessary_null_in_if_null_operators + - unnecessary_to_list_in_spreads + - use_is_even_rather_than_modulo + - use_super_parameters + +analyzer: + plugins: + - dart_code_linter + errors: + todo: ignore + use_build_context_synchronously: ignore + exclude: + - lib/l10n/*.dart + +dart_code_linter: + rules: + - avoid-dynamic + - avoid-redundant-async + - avoid-unnecessary-type-assertions + - avoid-unnecessary-type-casts + - avoid-unrelated-type-assertions + - no-equal-then-else + - prefer-first + - prefer-last + - prefer-immediate-return + - prefer-enums-by-name + - avoid-unnecessary-conditionals + - prefer-match-file-name + - member-ordering + - avoid-late-keyword + - avoid-global-state diff --git a/standards/dart/analysis_options.yaml b/standards/dart/analysis_options.yaml new file mode 100644 index 0000000..863b8f2 --- /dev/null +++ b/standards/dart/analysis_options.yaml @@ -0,0 +1,14 @@ +# Include the shared lint rules from engineering-standards. +# +# The standards file is managed by the engineering-standards flake; this file +# is yours to customise. Add repo-specific overrides below the include. +include: analysis_options.standards.yaml + +# Repo-specific overrides below this line. +# See https://dart.dev/tools/analysis for available options. Example: +# analyzer: +# exclude: +# - example/** +# linter: +# rules: +# avoid_print: false # https://github.com/famedly/REPO/issues/XXX From 46bab371588ef30027897f5bcd8a4d7c7b981428 Mon Sep 17 00:00:00 2001 From: Niklas Zender Date: Wed, 24 Jun 2026 15:14:26 +0200 Subject: [PATCH 2/2] feat(dart): Add dart format pre-commit hook When the repository has Dart projects, register a `dart format` hook in the root prek workspace and expose the pinned Dart SDK to the hook runner. Only formatting runs in prek since it is dependency-free; the dependency-aware checks (analyze, import_sorter, dart_code_linter) stay in the Dart CI workflow, which resolves packages first. Co-authored-by: Cursor --- nix/dart/default.nix | 1 + nix/dart/pre-commit.nix | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 nix/dart/pre-commit.nix diff --git a/nix/dart/default.nix b/nix/dart/default.nix index 2d28cd8..4524a2d 100644 --- a/nix/dart/default.nix +++ b/nix/dart/default.nix @@ -8,6 +8,7 @@ importingFlake: { imports = [ (importApply ./devshell.nix args) (importApply ./linting.nix args) + (importApply ./pre-commit.nix args) (importApply ./sdk.nix args) ./workflow.nix ]; diff --git a/nix/dart/pre-commit.nix b/nix/dart/pre-commit.nix new file mode 100644 index 0000000..d3af7c1 --- /dev/null +++ b/nix/dart/pre-commit.nix @@ -0,0 +1,40 @@ +# Dart pre-commit hooks. +# +# When the repository has Dart projects, register a `dart format` hook in the +# root `prek` workspace and make the pinned Dart SDK available to the hook +# runner. +# +# Only `dart format` runs here: it is dependency-free and fast. The +# dependency-aware checks (analyze, import_sorter, dart_code_linter, …) need +# `pub get` and therefore live in the Dart CI workflow instead of prek. +{ ... }: +importingFlake: { + perSystem = + { + config, + lib, + self', + ... + }: + lib.mkIf (config.famedly.standards.dart.projects != { }) { + prek-pre-commit = { + package.runtimePkgs = [ self'.packages.famedly-dart-sdk ]; + + workspaces.".".repos = [ + { + repo = "local"; + hooks = [ + { + id = "dart-format"; + name = "dart format"; + description = "Format Dart code with the pinned SDK"; + entry = "dart format"; + language = "system"; + types = [ "dart" ]; + } + ]; + } + ]; + }; + }; +}