diff --git a/nix/dart/default.nix b/nix/dart/default.nix index 0d005af..4524a2d 100644 --- a/nix/dart/default.nix +++ b/nix/dart/default.nix @@ -7,6 +7,8 @@ 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/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/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" ]; + } + ]; + } + ]; + }; + }; +} 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