flutter_prunekit 2.0.0 copy "flutter_prunekit: ^2.0.0" to clipboard
flutter_prunekit: ^2.0.0 copied to clipboard

Blazing-fast static analyzer for detecting unused classes, enums, mixins & extensions in Dart/Flutter. 100% precision, zero false positives.

Flutter PruneKit

flutter_prunekit #

🎯 Find and remove dead (unused) code in Dart & Flutter projects β€” classes, enums, mixins, extensions, methods and more.

Pub Version License: MIT Dart Flutter

Short, fast, zero-config static analysis to detect dead code and help keep your codebase small and maintainable.

Highlights β€’ Installation β€’ Quick Start β€’ Documentation


πŸš€ Why flutter_prunekit? #

Dead code bloats your app, confuses developers, and slows down builds. flutter_prunekit uses advanced static analysis to find unused classes, enums, mixins, and extensionsβ€”so you can ship faster, cleaner code.

✨ Highlights #

  • 🎯 High precision results backed by 370+ automated tests and production pilots (last validated Oct 2024).
  • ⚑ Analysis finishes in seconds for medium Flutter apps thanks to parallel AST traversal.
  • 🧠 Understands modern Dart features: extensions, mixins, part files, generics, override chains.
  • πŸ› οΈ Zero-config defaults with flexible ignore annotations, config, and glob patterns.
  • 🌍 Offline CLI that runs on macOS, Linux, and Windows with no external services.

πŸ” What it Detects #

Classes & Types:

  • βœ… Classes - Regular and abstract classes
  • βœ… Enums - All enum declarations
  • βœ… Mixins - Mixin declarations
  • βœ… Extensions - Named and unnamed extensions with full semantic analysis
    • Extension methods, getters, operators
    • Cross-file extension usage tracking
    • Generic type-parameterized extensions

Functions & Methods: πŸ†•

  • βœ… Top-level Functions - Global function declarations
  • βœ… Instance Methods - Class and enum instance methods with override detection
  • βœ… Static Methods - Class and enum static methods and factory constructors
  • βœ… Extension Methods - Methods on extension types
  • βœ… Getters & Setters - Property accessors (both top-level, class-level, and enum-level)
  • βœ… Operators - Overloaded operators (+, ==, [], etc.)
  • βœ… Private Methods - Unused private methods detection
  • βœ… Lifecycle Methods - Automatic exclusion of Flutter lifecycle methods (initState, dispose, etc.)

πŸš€ Coming Soon (Roadmap) #

We're actively working on detecting unused:

  • πŸ”œ Fields & Properties - Unused class fields
  • πŸ”œ Variables - Unused top-level and local variables
  • πŸ”œ Type aliases - Unused typedef declarations
  • πŸ”œ Constructor parameters - Unused named parameters

Want a feature? Open an issue!

πŸ“¦ Installation #

dart pub add --dev flutter_prunekit

Or manually add to pubspec.yaml:

dev_dependencies:
  flutter_prunekit: ^2.0.0

Then run:

dart pub get

Option 2: Global Installation #

dart pub global activate flutter_prunekit

πŸš€ Quick Start #

Basic Usage #

# Analyze your project (scans lib/ by default)
dart run flutter_prunekit

# Or if globally installed
flutter_prunekit

That's it! The tool will scan your code and show you any unused classes, enums, mixins, or extensions.

Example Output #

═══ Flutter Dead Code Analysis ═══

⚠ Found 5 unused declaration(s):

Classes: 2
Enums: 1

  lib/models/old_user.dart:12
    OldUser

  lib/widgets/legacy_button.dart:8
    LegacyButton

  lib/utils/deprecated_helper.dart:5
    DeprecatedStatus

Top-Level Functions: 1

  lib/helpers/formatter.dart:45
    formatLegacyData

Instance Methods: 1

  UserService (lib/services/user_service.dart:23)
    processLegacyUser [instance]

─── Summary ───

  Files analyzed: 156
  Total declarations: 89
  Total methods: 234
  Unused: 5
  Class usage rate: 96.6%
  Method usage rate: 99.1%

  Analysis time: 2.3s

Programmatic Usage #

Prefer to drive the analyzer from Dart code? Check out example/basic_usage.dart for a minimal script that wires together the public APIs to scan any project directory. Running it without arguments analyzes the bundled sample project:

dart run example/basic_usage.dart

This points the analyzer at example/sample_project, which deliberately contains unused classes, mixins, enums, and extensions so you can see the tool in action.

πŸ› οΈ CLI Reference #

Flag Description Default / Notes
--path <dir> Analyze specific directories instead of auto-detecting lib/. Repeatable; accepts globs.
--exclude <pattern> Ignore paths that match a glob (e.g. lib/legacy/**). Evaluated after --path.
--json Emit the full analysis report in JSON (matches formatter schema). Returns both class & method findings unless --only-methods.
--only-methods Skip class detection and report methods/functions only. Useful when classes are already clean.
--include-tests Analyze test/ alongside lib/. Default is disabled.
--include-generated Opt-in to scanning generated files (e.g. .g.dart). Works with flutter_prunekit.yaml excludes.
--ignore-analysis-options Ignore excludes from analysis_options.yaml. Handy for temporary deep scans.
--quiet Suppress banners and summaries; outputs only findings. Helpful for CI logs.
--verbose Print per-file progress and timing. Pair with CI to debug slow runs.
--help / -h Show the full help text with all options. Does not run analysis.
--version Print the current package version. Exits immediately.

πŸ“– Usage Guide #

Common Scenarios #

# Scope the scan
dart run flutter_prunekit --path packages/core/lib

# Exclude legacy modules
dart run flutter_prunekit --exclude 'lib/legacy/**'

# Include tests and generated code for a deep audit
dart run flutter_prunekit --include-tests --include-generated

# Debug a slow analysis
dart run flutter_prunekit --verbose

βš™οΈ Configuration #

Create flutter_prunekit.yaml in your project root:

# Exclude entire directories or specific files
exclude:
  - 'lib/legacy/**'           # All files in legacy folder
  - 'lib/generated/**'        # Generated code folder
  - '**/old_*.dart'          # Files starting with 'old_'
  - 'lib/deprecated.dart'    # Specific file

# Custom annotations to treat as "keep" markers
ignore_annotations:
  - 'deprecated'    # Classes with @deprecated won't be flagged
  - 'experimental'  # Your custom @experimental annotation

Method 2: Use Existing analysis_options.yaml #

The tool automatically respects your analyzer excludes:

analyzer:
  exclude:
    - 'lib/generated/**'
    - '**/*.g.dart'
    - '**/*.freezed.dart'

No additional configuration needed!

🎯 Ignoring False Positives #

Sometimes you need to keep code that appears unused (reflection, dynamic loading, etc.). Here's how:

Ignore Priority Order #

When multiple ignore methods conflict:

  1. @keepUnused annotation (highest)
  2. flutter_prunekit.yaml patterns
  3. --exclude CLI flag (lowest)

Perfect for individual classes or methods that should never be removed:

@keepUnused  // ← Add this annotation
class LegacyWidget extends StatelessWidget {
  // Won't be flagged as unused
}

@keepUnused
mixin ReflectionMixin {
  // Used via reflection - keep it!
}

@keepUnused
enum PlatformStatus { active, inactive }

@keepUnused
extension StringHelpers on String {
  // Extension used in other packages
}

class Calculator {
  @keepUnused  // Method-level annotation
  int complexCalculation() {
    // Used via reflection or dynamic invocation
    return 42;
  }
  
  int simpleAdd(int a, int b) => a + b;  // Normal method
}

Option 2: Pattern-Based Exclusion #

Use config file for excluding multiple files or specific methods:

# flutter_prunekit.yaml
exclude:
  - 'lib/legacy/**'              # Entire folder
  - '**/experimental_*.dart'     # Name pattern
  - 'lib/platform_specific.dart' # Single file

# Ignore specific methods by pattern
ignore_methods:
  - 'test*'                 # Ignore all test helper methods
  - '_internal*'            # Ignore internal methods
  - 'TestHelper.*'          # Ignore all TestHelper methods
  - '*.cleanup'             # Ignore cleanup in any class
  - 'debugPrint'            # Ignore specific method

Option 3: Runtime Exclusion (Temporary) #

Use CLI flags for one-off analyses:

# Test excluding certain code
dart run flutter_prunekit --exclude 'lib/legacy/**' --exclude '**/old_*.dart'

⚠️ Known Limitations (Edge Cases) #

These are rare but worth knowing:

1. Dynamic Type Usage

dynamic obj = getObject();
obj.method(); // ⚠️ Cannot statically determine class type

Solution: Avoid dynamic where possible, or use @keepUnused

2. Reflection & Mirrors

Type type = reflectClass(MyClass); // ⚠️ Runtime-only reference

Solution: Add @keepUnused to reflected classes

3. Conditional Imports (Platform-Specific Code)

import 'stub.dart' 
  if (dart.library.io) 'io_impl.dart'
  if (dart.library.html) 'web_impl.dart';

Solution: Annotate platform-specific classes with @keepUnused

4. Unnamed Extensions (Analyzer API Limitation)

// If ANY unnamed extension is used, ALL get marked as used
extension on String { ... }  // Shares identifier with below
extension on int { ... }     // Shares identifier with above

Solution: Use named extensions for better tracking:

extension StringHelpers on String { ... }
extension IntHelpers on int { ... }

πŸ—οΈ Code Generation Support #

βœ… Fully Supported #

  • Freezed - *.freezed.dart part files fully analyzed
  • Realm - *.realm.dart with $Model / _Model pattern
  • json_serializable - *.g.dart files
  • built_value - Generated builders and serializers

How It Works #

By default, generated files are excluded (recommended). Use --include-generated to analyze them:

# Include generated code in analysis
dart run flutter_prunekit --include-generated

⚠️ Note: Generated classes may appear unused if only referenced in other generated code. This is usually safe to ignore.

Best Practice: Run analysis both with and without --include-generated to understand your codebase.

Development Setup #

# Clone the repository
git clone https://github.com/furkanvatandas/flutter_prunekit.git
cd flutter_prunekit

# Install dependencies
dart pub get

# Run the tool locally
dart run bin/flutter_prunekit.dart --path lib

πŸ“„ License #

MIT License - see LICENSE file for details.

πŸ’¬ Support & Community #

⭐ Show Your Support #

If flutter_prunekit helped clean up your codebase, consider:

  • ⭐ Starring the repo
  • 🐦 Sharing on social media
  • πŸ“ Writing a blog post about it
6
likes
150
points
141
downloads

Publisher

unverified uploader

Weekly Downloads

Blazing-fast static analyzer for detecting unused classes, enums, mixins & extensions in Dart/Flutter. 100% precision, zero false positives.

Repository (GitHub)
View/report issues

Topics

#dart #flutter #static-analysis #dead-code #code-quality

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

analyzer, ansi_styles, args, glob, path, yaml

More

Packages that depend on flutter_prunekit