clean_code_lints 0.3.2 copy "clean_code_lints: ^0.3.2" to clipboard
clean_code_lints: ^0.3.2 copied to clipboard

Opinionated lint rules for clean architecture and clean code in Dart and Flutter projects.

clean_code_lints #

Opinionated lint rules for clean architecture and clean code in Dart and Flutter projects.

clean_code_lints is built on Dart's first-party analysis_server_plugin system — no custom_lint runner, no separate process. It targets the conventions most "clean architecture" Flutter projects converge on: layered folders, design tokens, small files, no framework leakage into domain code.

Requirements #

  • Dart SDK >= 3.10
  • Flutter >= 3.38 (if used in a Flutter project)

Install #

Enable the plugin and opt into the rules in your analysis_options.yaml:

plugins:
  clean_code_lints:
    version: ^0.3.2
    diagnostics:
      # Size & shape
      file_too_long: true
      function_too_long: true
      class_too_long: true
      build_method_too_long: true
      too_many_function_arguments: true

      # Naming
      single_letter_parameter: true
      hungarian_notation: true

      # Layered architecture
      domain_layer_imports: true
      presentation_imports_storage: true
      feature_isolation: true

      # Widget hygiene
      widget_level_try_catch: true
      widget_build_method: true

      # Hardcoded literals
      hardcoded_color: true
      hardcoded_spacing: true
      hardcoded_endpoint: true

      # Clean code
      no_print_in_production: true
      avoid_dynamic: true
      missing_await: true
      enum_exhaustive_switch: true

After editing plugins:, restart the Dart Analysis Server (IDE command "Dart: Restart Analysis Server" or restart your IDE) — the analyzer only re-reads the plugins: section on restart.

Diagnostics flow through the standard analyzer pipeline, so dart analyze and your IDE's Problems view both surface them.

Do not add clean_code_lints to your pubspec.yaml. Unlike custom_lint-era packages, native analyzer plugins are installed only through the plugins: section above. The analysis server resolves the plugin in its own isolated package context, so its analyzer dependency never meets your app's dependencies. Adding it to dev_dependencies instead pulls that analyzer constraint into your app's resolution, where it will conflict with codegen packages like freezed, json_serializable, or mockito.

Compatibility #

The plugin supports analyzer >=11.0.0 <15.0.0 (analysis_server_plugin >=0.3.11 <0.4.0), which covers Dart 3.10 and newer — pub automatically picks the pairing that matches your SDK. The range is kept deliberately wide because every plugin listed in an analysis_options.yaml resolves in one shared context: a plugin pinned to a single analyzer major conflicts with any neighbour pinned to a different one. Rules are written against AST APIs that are stable across the whole range (see lib/src/ast_compat.dart), and CI runs the full test suite against both edges.

Rules #

19 rules, all off by default. Enable them individually in diagnostics:.

Size & shape #

Rule Default cap What it flags
file_too_long 400 lines Any .dart file longer than the cap.
function_too_long 40 lines Function or method bodies longer than the cap.
class_too_long 300 lines Class declarations longer than the cap.
build_method_too_long 40 lines Widget build() bodies longer than the cap.
too_many_function_arguments 5 params Functions, methods, or constructors with more parameters than the cap.

Naming #

Rule What it flags
single_letter_parameter Parameter names with a single character (except the discard _).
hungarian_notation Identifiers prefixed with a type abbreviation (strName, boolFoo, etc.).

Layered architecture #

Rule What it flags
domain_layer_imports Files under lib/domain/ importing Flutter, infra packages, or sibling layers.
presentation_imports_storage Files under lib/presentation/ importing storage packages or the data layer.
feature_isolation Files under lib/features/<a>/ importing files under lib/features/<b>/.

Widget hygiene #

Rule What it flags
widget_level_try_catch try/catch inside a class extending Widget / State / ConsumerWidget / HookWidget etc.
widget_build_method Private _buildSomething() methods returning a Widget. Prefer a _Section widget class.

Hardcoded literals #

Rule What it flags
hardcoded_color Color(...) constructors and Colors.X references outside theme / token files.
hardcoded_spacing Numeric literals passed to SizedBox / EdgeInsets / Padding / Gap outside theme / token files.
hardcoded_endpoint String literals beginning with http:// or https:// outside config / endpoint files.

Clean code #

Rule What it flags
no_print_in_production Top-level print(...) calls outside test/, tool/, and bin/ directories.
avoid_dynamic Explicit dynamic type annotations outside test code.
missing_await Future-returning expressions used as statements without await, assignment, return, or unawaited(...).
enum_exhaustive_switch Switch statements on enum types that lack a default: clause and do not cover every constant.

Conventions assumed by path-based rules #

The rules below use path matching, not configuration. They expect a project layout where the relevant segment is somewhere in the file path:

  • domain_layer_imports — path contains /domain/.
  • presentation_imports_storage — path contains /presentation/.
  • feature_isolation — path matches /features/<feature_name>/.
  • hardcoded_color — allow-listed paths: /theme/, /colors/, /tokens/, /design_system/.
  • hardcoded_spacing — allow-listed paths: /theme/, /tokens/, /spacing/, /dimensions/, /design_system/.
  • hardcoded_endpoint — allow-listed paths: /api/, /endpoints/, /network/, /config/, /environment/.
  • no_print_in_production — allow-listed paths: /test/, /tool/, /bin/.
  • avoid_dynamic — allow-listed paths: /test/, files ending _test.dart.

These are opinionated v1 defaults. Configurable knobs (custom paths, custom caps, custom forbidden-import lists) are planned — see roadmap.

Local development #

To try the plugin against the bundled example:

cd example
flutter pub get
dart analyze

You should see diagnostics from multiple rules across example/lib/.

Roadmap #

Rules that need richer specs, deferred to a later milestone:

  • no_logic_in_build — flag side-effectful method calls in build() (needs careful spec to avoid false positives).
  • hardcoded_user_string — flag user-visible string literals (must integrate with intl / ARB / slang).
  • hardcoded_storage_key — flag string literals passed to storage APIs (needs target API knowledge).
  • Configurable variants of the path-based rules (custom layer paths, custom forbidden-import lists, custom size caps).

License #

MIT — see LICENSE.

1
likes
160
points
269
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Opinionated lint rules for clean architecture and clean code in Dart and Flutter projects.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

analysis_server_plugin, analyzer

More

Packages that depend on clean_code_lints