flutter_build_doctor 0.1.0
flutter_build_doctor: ^0.1.0 copied to clipboard
Automatically diagnose, explain, and fix common Flutter build issues. Gradle, CocoaPods, Xcode, Java, Kotlin version mismatches — detected and fixed in seconds. CLI tool + programmatic API.
example/flutter_build_doctor_example.dart
// ignore_for_file: avoid_print
import 'dart:io';
import 'package:flutter_build_doctor/flutter_build_doctor.dart';
import 'package:flutter_build_doctor/src/reports/terminal_report.dart';
import 'package:flutter_build_doctor/src/utils/logger.dart';
/// Example usage of Flutter Build Doctor.
///
/// Run from any Flutter project directory:
/// ```bash
/// dart run example/flutter_build_doctor_example.dart
/// ```
void main(List<String> args) async {
final logger = Logger.auto();
// Find project root
final projectRoot = _findProjectRoot();
if (projectRoot == null) {
print('❌ No Flutter project found.');
print(' Run this from a Flutter project directory,');
print(' or pass a path as argument:');
print('');
print(
' dart run example/flutter_build_doctor_example.dart /path/to/project',
);
exit(1);
}
print('📂 Project: $projectRoot\n');
final doctor = FlutterBuildDoctor(projectRoot: projectRoot);
// ─── Example 1: Full Diagnosis ──────────────────────────────────
logger.header('Example 1: Full Diagnosis');
final report = await doctor.diagnose();
TerminalReport(logger: logger).print(report);
// ─── Example 2: Programmatic Access ─────────────────────────────
logger.header('Example 2: Programmatic Access');
print(' Total checks: ${report.diagnoses.length}');
print(' Errors: ${report.errors.length}');
print(' Warnings: ${report.warnings.length}');
print(' Passed: ${report.passed.length}');
print(' Auto-fixable: ${report.autoFixable.length}');
print(' Is healthy: ${report.isHealthy}');
print('');
// ─── Example 3: Check Specific Issues ───────────────────────────
logger.header('Example 3: Individual Issue Details');
for (final d in report.diagnoses) {
print(
' [${d.severity.name.toUpperCase().padRight(7)}] '
'${d.title}',
);
if (d.currentValue != null) {
print(' Current: ${d.currentValue}');
}
if (d.expectedValue != null) {
print(' Expected: ${d.expectedValue}');
}
if (d.autoFixable) {
print(' 🔧 Auto-fixable');
}
print('');
}
// ─── Example 4: Version Compatibility Matrix ────────────────────
logger.header('Example 4: Version Compatibility Matrix');
for (final version in ['3.27', '3.24', '3.22', '3.19']) {
final compat = VersionMatrix.getCompatibility(version);
if (compat != null) {
print(' Flutter $version:');
print(' Gradle: ${compat.gradle}');
print(' AGP: ${compat.agp}');
print(' Kotlin: ${compat.kotlin}');
print(' Java: ${compat.java}');
print(' CocoaPods: ${compat.cocoapods}');
print(' Xcode: ${compat.xcode}');
print('');
}
}
// ─── Example 5: Version Comparison Utility ──────────────────────
logger.header('Example 5: Version Comparison');
final comparisons = [
['8.5', '7.6.3'],
['8.5', '8.5'],
['7.4.2', '8.3.0'],
['2.0.0', '1.9.24'],
['17', '11'],
];
for (final pair in comparisons) {
final a = pair[0];
final b = pair[1];
final result = VersionComparator.compare(a, b);
final symbol = result > 0
? '>'
: result < 0
? '<'
: '=';
print(' $a $symbol $b');
print(' isAtLeast($a, $b) = ${VersionComparator.isAtLeast(a, b)}');
print(' isBelow($a, $b) = ${VersionComparator.isBelow(a, b)}');
print('');
}
// ─── Example 6: Dry-Run Fixes ───────────────────────────────────
if (report.autoFixable.isNotEmpty) {
logger.header('Example 6: Dry-Run Fixes');
print(' Preview of what would be changed:\n');
for (final issue in report.autoFixable) {
final result = await doctor.fix(issue, dryRun: true);
print(' $result');
if (result.modifiedFiles.isNotEmpty) {
for (final file in result.modifiedFiles) {
print(' → $file');
}
}
print('');
}
} else {
logger.header('Example 6: No Fixes Needed');
print(' ✨ All checks passed! Nothing to fix.\n');
}
// ─── Example 7: Android-Only Diagnosis ──────────────────────────
logger.header('Example 7: Android-Only Diagnosis');
final androidReport = await doctor.diagnoseAndroid();
if (androidReport.diagnoses.isEmpty) {
print(' No Android directory found.\n');
} else {
print(' Android checks: ${androidReport.diagnoses.length}');
print(' Errors: ${androidReport.errors.length}');
print(' Warnings: ${androidReport.warnings.length}');
print('');
for (final d in androidReport.diagnoses) {
print(' $d');
}
print('');
}
// ─── Example 8: iOS-Only Diagnosis ──────────────────────────────
logger.header('Example 8: iOS-Only Diagnosis');
final iosReport = await doctor.diagnoseIos();
if (iosReport.diagnoses.isEmpty) {
print(' No iOS directory found or not running on macOS.\n');
} else {
print(' iOS checks: ${iosReport.diagnoses.length}');
print(' Errors: ${iosReport.errors.length}');
print(' Warnings: ${iosReport.warnings.length}');
print('');
for (final d in iosReport.diagnoses) {
print(' $d');
}
print('');
}
// ─── Example 9: Usage Stats ─────────────────────────────────────
logger.header('Example 9: Report Summary');
print(' Generated at: ${report.timestamp}');
print(' Project path: ${report.projectPath}');
print(' Flutter version: ${report.flutterVersion ?? "unknown"}');
print('');
// ─── Done ───────────────────────────────────────────────────────
logger.separator();
print(' All examples completed!');
print('');
print(' To use the CLI tool:');
print(' dart pub global activate flutter_build_doctor');
print(' flutter_build_doctor diagnose');
print(' flutter_build_doctor fix --auto');
print(' flutter_build_doctor clean');
print('');
}
/// Finds a Flutter project root from current directory or args.
String? _findProjectRoot([List<String>? args]) {
// Check if path passed as argument
if (args != null && args.isNotEmpty) {
final dir = Directory(args.first);
if (dir.existsSync()) {
final pubspec = File('${dir.path}/pubspec.yaml');
if (pubspec.existsSync()) return dir.path;
}
}
// Walk up from current directory
var dir = Directory.current;
for (int i = 0; i < 10; i++) {
final pubspec = File('${dir.path}/pubspec.yaml');
if (pubspec.existsSync()) return dir.path;
final parent = dir.parent;
if (parent.path == dir.path) break;
dir = parent;
}
return null;
}