Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Flutter Code Quality CheckerNew to Visual Studio Code? Get it now.
Flutter Code Quality Checker

Flutter Code Quality Checker

Vishal Gole

|
15 installs
| (0) | Free
Comprehensive Dart/Flutter code quality analyzer with 40+ rules across 11 categories — print statements, missing const, BLoC anti-patterns, unnecessary rebuilds, hardcoded values, dead code, API safety, null safety, async best practices, and separation of concerns. Get a 0-100 coding standard score
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Flutter Code Quality Checker

VS Code Marketplace License: MIT

🛡️ A comprehensive Dart/Flutter code quality analyzer with 48 rules across 10 categories — get a coding standard score, clickable inline issues, and fix suggestions.

✨ Features at a Glance

🔍 10 Powerful Analyzers

# Category What it Checks Rules
1 🖨️ Print Statements print(), debugPrint(), stdout.write() left in code 4
2 🏗️ Missing Const Widget constructors and lists that should use const 2
3 🧱 BLoC Anti-Patterns Side effects in BlocBuilder, missing close(), no Equatable 6
4 🔄 Unnecessary Rebuilds Controllers in build(), MediaQuery.of(), missing Keys 5
5 📝 Hardcoded Values Hardcoded strings, colors, URLs, dimensions in widgets 5
6 🧹 Clean Code Unused imports, dead code, empty catch, TODO/FIXME, commented URLs 8
7 🌐 API Usage Commented-out API calls, unhandled API errors, .catchError() 3
8 🔒 Null Safety Bang operator (!), late keyword, broken ?. chains 5
9 ⏳ Async Operations Missing mounted check, unawaited futures, async in initState 5
10 🏛️ Separation of Concerns API/DB calls in widgets, business logic in build(), large files 5

Total: 48 rules — all configurable, all with fix suggestions!


📊 Coding Standard Score (0-100)

Get a quality score with color-coded grades:

Score Grade Meaning
🟢 90-100 Excellent Production ready
🟡 70-89 Good Minor improvements needed
🟠 50-69 Needs Improvement Significant issues to address
🔴 0-49 Poor Major refactoring needed

The score uses weighted severity penalties: Errors (-5), Warnings (-3), Info (-1), Hints (-0.5). Project-wide scans scale logarithmically so large projects aren't unfairly penalized.


🖥️ Beautiful Bottom Panel UI

  • Score Gauge — Animated circular progress with color-coded grade
  • Issue Cards — Real-time counts of Errors, Warnings, Info, and Hints
  • Clickable Issues — Click any issue to jump directly to the problematic line
  • Filters & Sorting — Filter by category/severity; sort by file, line, or severity
  • Theme Support — Adapts to VS Code dark and light themes

🎯 Flexible Scope

  • Check Current File — Analyze just the active Dart file
  • Check Entire Project — Scan all Dart files in your workspace

⚡ Smart Exclusions

Automatically skips generated and non-production files:

  • *.g.dart, *.freezed.dart, *.mocks.dart
  • Test files (configurable)
  • Build directories and .dart_tool

🚀 Getting Started

Installation

  1. Open VS Code
  2. Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)
  3. Search for "Flutter Code Quality Checker"
  4. Click Install

Usage

  1. Open a Flutter/Dart project
  2. Open Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
  3. Type "Flutter Quality: Analyze Code Quality"
  4. Select "Check Current File" or "Check Entire Project"
  5. View results in the Flutter Quality panel at the bottom

You can also:

  • Click the shield icon in the editor title bar
  • Check the status bar for your last score
  • Use keyboard shortcut to re-analyze

📋 Rules Reference

🖨️ Print Statements

// ❌ Bad
print('debug value: $value');
debugPrint('something');

// ✅ Good
if (kDebugMode) {
  debugPrint('debug value: $value');
}

🏗️ Missing Const

// ❌ Bad — only flagged when arguments are true compile-time literals
Text('Hello World')
SizedBox(height: 16)
EdgeInsets.all(8.0)

// ✅ Good
const Text('Hello World')
const SizedBox(height: 16)
const EdgeInsets.all(8.0)

// ✅ NOT flagged — runtime values are correctly skipped
SizedBox(height: SizeConfig.h * AppSpacing.s36)
EdgeInsets.only(bottom: AppSpacing.s16)

🧱 BLoC Issues

// ❌ Bad — Side effect in BlocBuilder
BlocBuilder<MyBloc, MyState>(
  builder: (context, state) {
    Navigator.of(context).pop(); // Side effect!
    return Container();
  },
);

// ✅ Good — Use BlocListener for side effects
BlocListener<MyBloc, MyState>(
  listener: (context, state) {
    Navigator.of(context).pop();
  },
  child: BlocBuilder<MyBloc, MyState>(
    builder: (context, state) => Container(),
  ),
);

🔄 Unnecessary Rebuilds

// ❌ Bad — Controller created in build()
Widget build(BuildContext context) {
  final controller = TextEditingController(); // Recreated every build!
  return TextField(controller: controller);
}

// ✅ Good
late final _controller = TextEditingController();
Widget build(BuildContext context) {
  return TextField(controller: _controller);
}

🔒 Null Safety

// ❌ Bad — Force unwrap risks runtime crash
final name = user!.name;
final first = list.first!;

// ✅ Good
final name = user?.name ?? 'Unknown';
final first = list.firstOrNull;

⏳ Async Operations

// ❌ Bad — Using context after async gap without mounted check
Future<void> _onSubmit() async {
  await repository.save(data);
  Navigator.of(context).pop(); // Widget might be disposed!
}

// ✅ Good
Future<void> _onSubmit() async {
  await repository.save(data);
  if (!mounted) return;
  Navigator.of(context).pop();
}

🌐 API Usage

// ❌ Bad — API call without error handling
final response = await http.get(Uri.parse(url));

// ✅ Good
try {
  final response = await http.get(Uri.parse(url));
} catch (e) {
  // Handle error gracefully
}

🏛️ Separation of Concerns

// ❌ Bad — API call directly in widget
class MyWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    final response = await http.get(url); // Direct API call!
    return Text(response.body);
  }
}

// ✅ Good — Use Repository + BLoC/Provider pattern
class MyWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    return BlocBuilder<MyBloc, MyState>(
      builder: (context, state) => Text(state.data),
    );
  }
}

🧹 Clean Code

// ❌ Bad — Commented-out code and URLs
// final data = await fetchData();
// final result = transform(data);
// https://api.old-server.com/v1/users

// ✅ Good — Use version control, not comments
// Use proper configuration for URLs

⚙️ Configuration

Open Settings (Ctrl+,) and search for "Flutter Quality Checker":

Setting Default Description
enablePrintCheck true Check for print statements
enableConstCheck true Check for missing const keywords
enableBlocCheck true Check for BLoC anti-patterns
enableRebuildCheck true Check for unnecessary rebuilds
enableHardcodedCheck true Check for hardcoded values
enableCleanCodeCheck true Check for dead code, unused imports, TODO/FIXME
enableApiCheck true Check for API call issues
enableNullSafetyCheck true Check for null safety issues
enableAsyncCheck true Check for async operation issues
enableSeparationCheck true Check for separation of concerns
excludePatterns ["**/*.g.dart", ...] Glob patterns to exclude
excludeTestFiles true Exclude test files from analysis

📈 Scoring System

Severity Points Deducted Examples
🔴 Error -5 per issue Missing mounted check, controller in build(), unhandled API
⚠️ Warning -3 per issue print(), hardcoded URLs, force unwrap (!)
ℹ️ Info -1 per issue Missing const, hardcoded strings, TODO comments
💡 Hint -0.5 per issue debugPrint(), commented-out code, hardcoded dimensions

For project-wide scans, deductions scale logarithmically with file count — so a few issues in a big project don't tank your score.

📋 Complete Rules, Severity & Scoring Matrix

Each rule belongs to one of the 10 Categories and carries a specific Severity, which translates directly into score deductions:

Category Rule ID Severity Deduction Description
🖨️ Print Statements print-statement ⚠️ Warning -3.0 Bare print() statements left in production code.
debug-print 💡 Hint -0.5 Bare debugPrint() statements left in code.
🏗️ Missing Const missing-const-widget ℹ️ Info -1.0 Eligible Widget constructors invoked without const.
missing-const-list 💡 Hint -0.5 Eligible child lists invoked without const.
🧱 BLoC Issues bloc-side-effect-in-builder 🔴 Error -5.0 Navigation or side-effects inside BlocBuilder.
bloc-missing-close 🔴 Error -5.0 BLoC/Cubit instantiated but not closed in dispose().
bloc-state-no-equatable ⚠️ Warning -3.0 BLoC state class not extending Equatable.
bloc-builder-no-buildwhen 💡 Hint -0.5 Missing buildWhen logic in complex widgets.
bloc-use-multi-provider 💡 Hint -0.5 Multiple nested Providers instead of MultiProvider.
bloc-direct-emit 🔴 Error -5.0 Emitting state outside of events/handlers in BLoC.
🔄 Unnecessary Rebuilds rebuild-controller-in-build 🔴 Error -5.0 Creating animation/text controllers in build().
rebuild-object-in-build ⚠️ Warning -3.0 Allocating styling objects (BoxDecoration/TextStyle) in build().
rebuild-mediaquery-of ⚠️ Warning -3.0 Using MediaQuery.of(context) instead of granular selectors.
rebuild-missing-key ℹ️ Info -1.0 Custom widgets in lists instantiated without Key.
rebuild-setstate-with-statemgmt ℹ️ Info -1.0 Using setState() in a file importing BLoC/Provider.
📝 Hardcoded Values hardcoded-string ℹ️ Info -1.0 Hardcoded string literals in UI widgets.
hardcoded-color ℹ️ Info -1.0 Hardcoded color literals (Color(0xFF...)) in widgets.
hardcoded-dimension 💡 Hint -0.5 Hardcoded double literals (width/height/padding) in UI.
hardcoded-font-size 💡 Hint -0.5 Hardcoded font sizes in TextStyle constructors.
hardcoded-url ⚠️ Warning -3.0 Hardcoded API/server URL strings in widgets.
🧹 Clean Code clean-unused-import ⚠️ Warning -3.0 Import statements where symbols are never referenced.
clean-duplicate-import ⚠️ Warning -3.0 The exact same file/package imported multiple times.
clean-unused-variable ⚠️ Warning -3.0 Local variable declared but never used in functions.
clean-empty-catch ⚠️ Warning -3.0 catch (e) {} blocks with no handling logic.
clean-todo-comment ℹ️ Info -1.0 TODO, FIXME, HACK, or XXX comments left in code.
clean-commented-code 💡 Hint -0.5 Multiple lines of commented-out code blocks.
clean-commented-url ⚠️ Warning -3.0 Commented-out URL strings (// http://...).
clean-empty-block ⚠️ Warning -3.0 Empty if, else, for, while statement blocks.
🌐 API Usage api-commented-call ⚠️ Warning -3.0 Commented-out API/HTTP calls (e.g. // http.get(...)).
api-prefer-try-catch 💡 Hint -0.5 Using .catchError() instead of idiomatic try-catch blocks.
api-unhandled-error 🔴 Error -5.0 Async API/repository calls not wrapped in try-catch.
🔒 Null Safety null-bang-operator ⚠️ Warning -3.0 Force unwrap (!) operator risks runtime crash.
null-late-keyword ℹ️ Info -1.0 late variable declarations risk uninitialized errors.
null-unchecked-nullable 🔴 Error -5.0 Unsafe casts (as T) or map key accesses without null check.
null-chain-risk 🔴 Error -5.0 Broken ?. chain like obj?.prop.method() causing crash.
null-assert-collection ⚠️ Warning -3.0 Force unwrap on collection operators like list.first!.
⏳ Async Operations async-missing-mounted 🔴 Error -5.0 Using context after async gaps without checking mounted.
async-no-await 💡 Hint -0.5 Async functions containing no await statements.
async-unawaited-future ⚠️ Warning -3.0 Calling futures without await or assigning to variable.
async-in-initstate 🔴 Error -5.0 Direct async/await calls inside initState().
async-fire-and-forget 🔴 Error -5.0 Async operations triggered without error handling catch blocks.
🏛️ Separation of Concerns separation-api-in-widget 🔴 Error -5.0 Direct HTTP or repository network calls in widget classes.
separation-db-in-widget 🔴 Error -5.0 Direct SharedPreferences or database access inside widgets.
separation-logic-in-build 🔴 Error -5.0 Heavy arithmetic or non-widget business logic in build().
separation-state-in-widget ⚠️ Warning -3.0 Excessive setState() calls in a single widget file.
separation-large-file ℹ️ Info -1.0 Widget files exceeding 300 lines of code.

🤝 Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

📄 License

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


Made with ❤️ for the Flutter community by Vishal Gole

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft