runScan function
- Directory? source,
- RuntimeScannerConfiguration? config,
- bool forceLoadLibraries = false,
- OnLogged? onInfo,
- OnLogged? onWarning,
- OnLogged? onError,
- List<
String> args = const [], - RuntimeScanner? configuredScanner,
- bool overrideConfig = false,
Executes a full application runtime scan, builds a runtime context, and registers it globally.
This method is the primary entry point for initializing JetLeaf’s runtime model in real applications. It orchestrates:
- Source discovery
- Package scanning and exclusion
- Declaration and link generation
- Runtime context creation
The resulting runtime context is automatically registered into Runtime, making all scanned types, hints, and declarations immediately available for runtime execution.
Parameters
source
Optional root Directory used as the base for scanning.
If omitted, the scanner will infer the source root using the current working directory and runtime environment.
This is commonly used when:
- Running scans in monorepos
- Testing alternate project layouts
- Executing scans from tooling or build systems
config
Optional RuntimeScannerConfiguration used to customize scanning behavior.
When provided, this configuration is merged with JetLeaf’s default production-safe configuration:
- Default exclusions are preserved
- Provided values override defaults selectively
This prevents accidental scanning of:
- Tests
- Tooling
- Build artifacts
- Analyzer internals
forceLoadLibraries
Forces all discovered libraries to be loaded eagerly.
This flag is useful when:
- Performing deep reflection analysis
- Generating complete declaration graphs
- Debugging missing type resolution
If config.forceLoadLibraries is set, it takes precedence over this value.
onInfo, onWarning, onError
Optional logging callbacks invoked during scanning.
If not provided, default handlers print messages to stdout using clearly distinguishable markers:
(∞INFO∞)(∞WARN∞)(∞ERROR∞)
These callbacks allow integration with structured loggers, CI pipelines, or developer tooling.
args
Command-line arguments forwarded to the scanner.
These arguments may influence:
- Conditional compilation
- Environment-specific scanning logic
- Feature toggles used by generators
Configuration Merging Strategy
The scanner builds a derived configuration that:
- Uses JetLeaf-safe defaults
- Applies user overrides selectively
- Preserves exclusion rules critical to performance and correctness
Key defaults include:
- Skipping test directories
- Excluding analyzer and compiler internals
- Preventing accidental scans of
.dart_toolandbuilddirectories
Execution Flow
- An ApplicationRuntimeScanner is instantiated with logging hooks.
- A merged RuntimeScannerConfiguration is constructed.
- The scanner performs a full runtime scan using:
- The resolved configuration
- Command-line arguments
- Optional source directory
- A RuntimeScannerSummary is produced.
- The resulting runtime context is registered globally via
Runtime.register.
Returns
A RuntimeScannerSummary containing:
- Scan statistics
- Discovered libraries and declarations
- Generated runtime context
This object can be used for:
- Diagnostics
- Build tooling
- Reporting and analysis
Example
final summary = await runScan(
source: Directory('lib'),
config: RuntimeScannerConfiguration(
enableTreeShaking: true,
),
);
print('Scanned ${summary.libraryCount} libraries');
Intended Use Cases
- Application startup initialization
- Build-time runtime generation
- Tooling and code generation pipelines
- Production runtime bootstrapping
See Also
Implementation
Future<RuntimeScannerSummary> runScan({
Directory? source,
RuntimeScannerConfiguration? config,
bool forceLoadLibraries = false,
OnLogged? onInfo,
OnLogged? onWarning,
OnLogged? onError,
List<String> args = const [],
RuntimeScanner? configuredScanner,
bool overrideConfig = false
}) async {
final scanner = configuredScanner ?? ApplicationRuntimeScanner(
onInfo: onInfo ?? (msg, overwrite) => print("(∞INFO∞) ${overwrite ? '\r$msg' : msg}"),
onWarning: onWarning ?? (msg, overwrite) => print("(∞WARN∞) ${overwrite ? '\r$msg' : msg}"),
onError: onError ?? (msg, overwrite) => print("(∞ERROR∞) ${overwrite ? '\r$msg' : msg}"),
);
final defaultConfig = RuntimeScannerConfiguration(
skipTests: config?.skipTests ?? true,
reload: config?.reload ?? true,
packagesToScan: config?.packagesToScan ?? [],
packagesToExclude: [
'collection',
'analyzer',
'_fe_analyzer',
"r:.*/example/.*",
"r:.*/test/.*",
"r:.*/tool/.*",
"r:.*/benchmark/.*",
"r:.*/.dart_tool/.*",
"r:.*/build/.*",
...config?.packagesToExclude ?? []
],
additions: config?.additions ?? [],
updateAssets: config?.updateAssets ?? false,
writeDeclarationsToFiles: config?.writeDeclarationsToFiles ?? false,
forceLoadLibraries: config?.forceLoadLibraries ?? forceLoadLibraries,
scanClasses: config?.scanClasses ?? [],
filesToScan: config?.filesToScan ?? [],
filesToExclude: config?.filesToExclude ?? [],
enableTreeShaking: config?.enableTreeShaking ?? false,
excludeClasses: config?.excludeClasses ?? [],
updatePackages: config?.updatePackages ?? false,
removals: config?.removals ?? [],
outputPath: config?.outputPath ?? "build/generated"
);
return await scanner.scan(overrideConfig ? config ?? defaultConfig : defaultConfig, args, source: source);
}