run method
The execution body of the command.
Implementation
@override
Future<void> run(List<String> args, {required Logger logger}) async {
final finder = ProjectFinder();
final projectRoot = finder.findProjectRoot();
final project = FlutterProject(projectRoot);
final configManager = ConfigManager(projectRoot);
if (!configManager.configExists()) {
logger.error('No deep link configuration found. Please run "deeplink init" first.');
return;
}
final config = configManager.load();
logger.println('=== Deep Link Integration Doctor Report ===\n');
var allPassed = true;
// 1. Check Configuration Scheme
if (config.schemes.isEmpty) {
logger.error('No scheme configured in ${Constants.configFile}');
allPassed = false;
} else {
logger.success('Configuration schemes: ${config.schemes.join(", ")}');
}
// 2. Check Android Manifest
if (FileUtils.exists(project.androidManifestPath)) {
final manifestContent = FileUtils.readAsString(project.androidManifestPath);
var manifestOk = true;
for (final scheme in config.schemes) {
if (!manifestContent.contains('android:scheme="$scheme"')) {
logger.error('AndroidManifest.xml: Missing intent-filter data tag for scheme "$scheme".');
manifestOk = false;
allPassed = false;
}
}
if (config.androidAppLinks) {
if (!manifestContent.contains('android:autoVerify="true"')) {
logger.warning('AndroidManifest.xml: Android App Links enabled, but missing android:autoVerify="true" attribute.');
}
}
if (manifestOk) {
logger.success('AndroidManifest.xml is configured correctly.');
}
} else {
logger.error('AndroidManifest.xml not found at ${project.androidManifestPath}');
allPassed = false;
}
// 3. Check MainActivity code injection
try {
final mainActivityInfo = project.findMainActivity();
final content = FileUtils.readAsString(mainActivityInfo.path);
if (content.contains('custom_deeplink') || content.contains('DEEPLINK_CHANNEL')) {
logger.success('MainActivity (${mainActivityInfo.language.name}) has MethodChannel code injected.');
} else {
logger.error('MainActivity (${mainActivityInfo.language.name}): Missing MethodChannel and deep linking hooks.');
allPassed = false;
}
} catch (e) {
logger.error('MainActivity verification failed: ${e.toString()}');
allPassed = false;
}
// 4. Check iOS Info.plist
if (FileUtils.exists(project.iosPlistPath)) {
final plistContent = FileUtils.readAsString(project.iosPlistPath);
var plistOk = true;
for (final scheme in config.schemes) {
if (!plistContent.contains('<string>$scheme</string>')) {
logger.error('Info.plist: Missing CFBundleURLSchemes entry for scheme "$scheme".');
plistOk = false;
allPassed = false;
}
}
if (plistOk) {
logger.success('Info.plist is configured correctly.');
}
} else {
logger.error('Info.plist not found at ${project.iosPlistPath}');
allPassed = false;
}
// 5. Check iOS AppDelegate Swift file
if (FileUtils.exists(project.iosAppDelegatePath)) {
final content = FileUtils.readAsString(project.iosAppDelegatePath);
if (content.contains('custom_deeplink') && content.contains('FlutterMethodChannel')) {
logger.success('AppDelegate.swift has MethodChannel and url delegates injected.');
} else {
logger.error('AppDelegate.swift: Missing MethodChannel or delegate handlers.');
allPassed = false;
}
} else {
logger.error('AppDelegate.swift not found at ${project.iosAppDelegatePath}');
allPassed = false;
}
// 6. Check Generated Flutter files
final expectedFiles = [
'deep_link_service.dart',
'deep_link_route.dart',
'deep_link_parser.dart',
'deep_link_routes.dart',
'deep_link_constants.dart',
'deep_link_utils.dart',
if (config.generateDeepLinkManager) 'deep_link_manager.dart',
];
var flutterFilesOk = true;
for (final filename in expectedFiles) {
final path = PathUtils.join(projectRoot, Constants.libDeepLinkDir, filename);
if (!FileUtils.exists(path)) {
logger.error('Flutter Deep Link file missing: $filename');
flutterFilesOk = false;
allPassed = false;
}
}
if (flutterFilesOk) {
logger.success('All required Flutter deep linking source files exist.');
}
logger.println('');
if (allPassed) {
logger.success('Doctor found NO issues. Your deep linking configuration is healthy.');
} else {
logger.warning('Doctor found issues that need fixing. Run "deeplink init" or "deeplink regenerate" to resolve them.');
}
}