code_craft_lints

pub package Dart SDK License: MIT PRs Welcome

A high-performance Dart Analysis Server Plugin providing strict architectural rules, cyclomatic complexity reduction, and automated quick fixes for Dart and Flutter codebases.

Built directly on the modern official analysis_server_plugin framework, code_craft_lints integrates seamlessly with your IDE (VS Code, Android Studio, IntelliJ) and CI/CD pipelines via standard dart analyze and dart fix.


Table of Contents


Features

  • ⚑ Official Analyzer Plugin: Built using Dart's native analysis_server_plugin for fast, real-time feedback without extra background processes.
  • πŸ› οΈ Automated Quick Fixes: Fix issues instantly in your editor (Alt+Enter / Cmd+.) or across your entire repository with dart fix --apply.
  • πŸ“ Clean Architecture & Object Calisthenics: Enforces single-statement blocks, flat indentation, and strict class modifier hierarchies.
  • πŸ§ͺ 100% Tested: Every rule, AST edge case, and fix producer is rigorously tested.

Installation

Add code_craft_lints to your pubspec.yaml under dev_dependencies:

dev_dependencies:
  code_craft_lints: ^1.1.0

Then install the dependencies:

dart pub get
# or for Flutter projects
flutter pub get

Configuration

Enable the plugin in your project's analysis_options.yaml:

plugins:
  code_craft_lints:

Once enabled, restart your IDE's Dart Analysis Server or run:

dart analyze

Automatic Fixing

Many rules provided by code_craft_lints include automated quick fixes.

In your IDE

Press Alt + Enter (Windows/Linux) or Cmd + . (macOS) on any highlighted warning to preview and apply the fix.

Across your entire project

Apply all available automated fixes in one command:

dart fix --apply

Rules & Fixes Catalog

Rule Severity Automated Fix Description
prefer_ternary Warning βœ… Yes Prefer ternary operators for simple returns and assignments.
pure_contract_class Warning βœ… Yes Declare pure contract classes as abstract interface class.
final_implementation_class Warning βœ… Yes Declare concrete implementation classes as final class or base class.
max_two_level_of_indentation Warning ❌ Manual Enforce at most 2 levels of indentation per function.
one_statement_per_block Warning ❌ Manual Ensure control blocks contain at most one statement.

prefer_ternary

Severity: Warning
Diagnostic Code: prefer_ternary
Automated Fix: Convert to ternary operator

Rationale

Using multi-line if/else statements solely to return different values or assign to the same variable creates unnecessary boilerplate and increases cognitive load. Modern Dart concise expressions improve readability and reduce nesting.

Return Statements

❌ Bad
String formatStatus(bool isActive) {
  if (isActive) {
    return 'Active';
  } else {
    return 'Inactive';
  }
}
βœ… Good
String formatStatus(bool isActive) {
  return isActive ? 'Active' : 'Inactive';
}

Assignment Statements

❌ Bad
void updateStatus(bool isActive) {
  String status;
  if (isActive) {
    status = 'Active';
  } else {
    status = 'Inactive';
  }
}
βœ… Good
void updateStatus(bool isActive) {
  String status;
  status = isActive ? 'Active' : 'Inactive';
}

pure_contract_class

Severity: Warning
Diagnostic Code: pure_contract_class
Automated Fix: Add 'interface' modifier

Rationale

In Dart 3+, abstract class allows both interface implementation (implements) and subclassing (extends). If an abstract class contains no concrete method implementations and no instance fields, it represents a pure contract and should be explicitly declared as abstract interface class to prevent unintended code reuse and define a strict API boundary.

❌ Bad
abstract class UserRepository {
  Future<User> findById(String id);
  Future<void> save(User user);
}
βœ… Good
abstract interface class UserRepository {
  Future<User> findById(String id);
  Future<void> save(User user);
}

final_implementation_class

Severity: Warning
Diagnostic Code: final_implementation_class
Automated Fixes:

  • Add 'final' modifier (Recommended)
  • Add 'base' modifier

Rationale

Concrete classes without class modifiers are open for subclassing, implementation, and mixing outside their defining library. This can lead to fragile base class problems and broken encapsulation. Concrete classes should be declared final class (or base class if inheritance across libraries is explicitly intended).

❌ Bad
class Authenticator {
  void authenticate() {
    // Concrete implementation
  }
}
βœ… Good
final class Authenticator {
  void authenticate() {
    // Concrete implementation
  }
}

Or, if subclassing is explicitly supported:

base class Authenticator {
  void authenticate() {
    // Concrete implementation
  }
}

max_two_level_of_indentation

Severity: Warning
Diagnostic Code: max_two_level_of_indentation
Automated Fix: Manual refactoring / helper extraction

Rationale

Rooted in Object Calisthenics, this rule mandates that a single function body should not exceed 2 levels of indentation (Level 0: function declaration, Level 1: function body, Level 2: first-level control flow block, Level 3+: nested control flow violation). Deeply nested control flow ("arrowhead anti-pattern") makes functions difficult to reason about, test, and maintain.

❌ Bad
void processOrders(List<Order> orders) {
  for (final order in orders) {
    if (order.isValid) { // ⚠️ Level 3 (nested control flow inside for-loop)!
      ship(order);
    }
  }
}
βœ… Good
void processOrders(List<Order> orders) {
  for (final order in orders) {
    _processSingleOrder(order);
  }
}

void _processSingleOrder(Order order) {
  if (order.isValid) {
    ship(order);
  }
}

one_statement_per_block

Severity: Warning
Diagnostic Code: one_statement_per_block
Automated Fix: Manual refactoring / helper extraction

Rationale

Encourages small, single-responsibility blocks. Any block within a control structure (if, for, while, try, catch, finally) should contain at most one statement. If a branch requires multiple operations, extract that sequence into a well-named helper method.

❌ Bad
void handleResponse(Response response) {
  if (response.isSuccess) {
    logResponse(response); // ⚠️ Block contains 2 statements
    updateUi(response.body);
  }
}
βœ… Good
void handleResponse(Response response) {
  if (response.isSuccess) {
    _onSuccess(response);
  }
}

void _onSuccess(Response response) {
  logResponse(response);
  updateUi(response.body);
}

Disabling Rules

Ignore a rule for a specific line

Add an // ignore: comment above the line:

// ignore: prefer_ternary
if (isReady) {
  return true;
} else {
  return false;
}

Ignore a rule for an entire file

Add an // ignore_for_file: comment at the very top of the file:

// ignore_for_file: pure_contract_class

Contributing

We welcome contributions! Please review CONTRIBUTING.md before submitting a pull request.

⚠️ Strict Quality Guideline: In this repository, every single line of code and branch must be backed by comprehensive unit tests.


License

This project is licensed under the MIT License - see the LICENSE file for details.

Libraries

code_craft_lints
A powerful Dart analyzer plugin enforcing clean architecture, indentation limits, and strict class modifiers with automated quick fixes.
main
Plugin registration entry point for custom analyzer lints and quick fixes.